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
018 package org.apache.logging.log4j.core.net.server;
019
020 import java.util.concurrent.atomic.AtomicReference;
021 import javax.jms.JMSException;
022 import javax.jms.Message;
023 import javax.jms.MessageConsumer;
024 import javax.jms.MessageListener;
025 import javax.jms.ObjectMessage;
026
027 import org.apache.logging.log4j.Logger;
028 import org.apache.logging.log4j.LoggingException;
029 import org.apache.logging.log4j.core.LifeCycle;
030 import org.apache.logging.log4j.core.LogEvent;
031 import org.apache.logging.log4j.core.LogEventListener;
032 import org.apache.logging.log4j.core.appender.mom.JmsManager;
033 import org.apache.logging.log4j.core.net.JndiManager;
034 import 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 */
041 public 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 }