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.io.BufferedReader; 021import java.io.IOException; 022import java.io.InputStreamReader; 023import java.nio.charset.Charset; 024import java.util.concurrent.atomic.AtomicReference; 025import javax.jms.JMSException; 026import javax.jms.Message; 027import javax.jms.MessageConsumer; 028import javax.jms.MessageListener; 029import javax.jms.ObjectMessage; 030 031import org.apache.logging.log4j.LoggingException; 032import org.apache.logging.log4j.core.LifeCycle; 033import org.apache.logging.log4j.core.LogEvent; 034import org.apache.logging.log4j.core.LogEventListener; 035import org.apache.logging.log4j.core.appender.mom.JmsManager; 036import org.apache.logging.log4j.core.net.JndiManager; 037 038/** 039 * LogEventListener server that receives LogEvents over a JMS {@link javax.jms.Destination}. 040 * 041 * @since 2.1 042 */ 043public class JmsServer extends LogEventListener implements MessageListener, LifeCycle { 044 045 private final AtomicReference<State> state = new AtomicReference<>(State.INITIALIZED); 046 private final JmsManager jmsManager; 047 private MessageConsumer messageConsumer; 048 049 public JmsServer(final String connectionFactoryBindingName, 050 final String destinationBindingName, 051 final String username, 052 final String password) { 053 final String managerName = JmsServer.class.getName() + '@' + JmsServer.class.hashCode(); 054 final JndiManager jndiManager = JndiManager.getDefaultManager(managerName); 055 jmsManager = JmsManager.getJmsManager(managerName, jndiManager, connectionFactoryBindingName, 056 destinationBindingName, username, password); 057 } 058 059 @Override 060 public State getState() { 061 return state.get(); 062 } 063 064 @Override 065 public void onMessage(final Message message) { 066 try { 067 if (message instanceof ObjectMessage) { 068 final Object body = ((ObjectMessage) message).getObject(); 069 if (body instanceof LogEvent) { 070 log((LogEvent) body); 071 } else { 072 LOGGER.warn("Expected ObjectMessage to contain LogEvent. Got type {} instead.", body.getClass()); 073 } 074 } else { 075 LOGGER.warn("Received message of type {} and JMSType {} which cannot be handled.", message.getClass(), 076 message.getJMSType()); 077 } 078 } catch (final JMSException e) { 079 LOGGER.catching(e); 080 } 081 } 082 083 @Override 084 public void initialize() { 085 } 086 087 @Override 088 public void start() { 089 if (state.compareAndSet(State.INITIALIZED, State.STARTING)) { 090 try { 091 messageConsumer = jmsManager.createMessageConsumer(); 092 messageConsumer.setMessageListener(this); 093 } catch (final JMSException e) { 094 throw new LoggingException(e); 095 } 096 } 097 } 098 099 @Override 100 public void stop() { 101 try { 102 messageConsumer.close(); 103 } catch (final JMSException ignored) { 104 } 105 jmsManager.release(); 106 } 107 108 @Override 109 public boolean isStarted() { 110 return state.get() == State.STARTED; 111 } 112 113 @Override 114 public boolean isStopped() { 115 return state.get() == State.STOPPED; 116 } 117 118 /** 119 * Starts and runs this server until the user types "exit" into standard input. 120 * 121 * @throws IOException 122 * @since 2.6 123 */ 124 public void run() throws IOException { 125 this.start(); 126 System.out.println("Type \"exit\" to quit."); 127 final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in, Charset.defaultCharset())); 128 while (true) { 129 final String line = stdin.readLine(); 130 if (line == null || line.equalsIgnoreCase("exit")) { 131 System.out.println("Exiting. Kill the application if it does not exit due to daemon threads."); 132 this.stop(); 133 return; 134 } 135 } 136 } 137 138}