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 static final Logger LOGGER = StatusLogger.getLogger(); 044 private final AtomicReference<State> state = new AtomicReference<State>(State.INITIALIZED); 045 private final JmsManager jmsManager; 046 private MessageConsumer messageConsumer; 047 048 public JmsServer(final String connectionFactoryBindingName, 049 final String destinationBindingName, 050 final String username, 051 final String password) { 052 final String managerName = JmsServer.class.getName() + '@' + JmsServer.class.hashCode(); 053 final JndiManager jndiManager = JndiManager.getDefaultManager(managerName); 054 jmsManager = JmsManager.getJmsManager(managerName, jndiManager, connectionFactoryBindingName, 055 destinationBindingName, username, password); 056 } 057 058 @Override 059 public State getState() { 060 return state.get(); 061 } 062 063 @Override 064 public void onMessage(final Message message) { 065 try { 066 if (message instanceof ObjectMessage) { 067 final Object body = ((ObjectMessage) message).getObject(); 068 if (body instanceof LogEvent) { 069 log((LogEvent) body); 070 } else { 071 LOGGER.warn("Expected ObjectMessage to contain LogEvent. Got type {} instead.", body.getClass()); 072 } 073 } else { 074 LOGGER.warn("Received message of type {} and JMSType {} which cannot be handled.", message.getClass(), 075 message.getJMSType()); 076 } 077 } catch (final JMSException e) { 078 LOGGER.catching(e); 079 } 080 } 081 082 @Override 083 public void start() { 084 if (state.compareAndSet(State.INITIALIZED, State.STARTING)) { 085 try { 086 messageConsumer = jmsManager.createMessageConsumer(); 087 messageConsumer.setMessageListener(this); 088 } catch (final JMSException e) { 089 throw new LoggingException(e); 090 } 091 } 092 } 093 094 @Override 095 public void stop() { 096 try { 097 messageConsumer.close(); 098 } catch (final JMSException ignored) { 099 } 100 jmsManager.release(); 101 } 102 103 @Override 104 public boolean isStarted() { 105 return state.get() == State.STARTED; 106 } 107 108 @Override 109 public boolean isStopped() { 110 return state.get() == State.STOPPED; 111 } 112 113}