/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2006-2011 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/
package org.opennms.netmgt.utils;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import org.opennms.core.utils.InetAddressUtils;
import org.opennms.core.utils.ThreadCategory;
import org.opennms.core.xml.JaxbUtils;
import org.opennms.netmgt.model.events.EventProxy;
import org.opennms.netmgt.model.events.EventProxyException;
import org.opennms.netmgt.xml.event.Event;
import org.opennms.netmgt.xml.event.Events;
import org.opennms.netmgt.xml.event.Log;
/**
* This is the interface used to send events into the event subsystem - It is
* typically used by the poller framework plugins that perform service
* monitoring to send out appropriate events. Can also be used by capsd,
* discovery etc.
*
* @author <A HREF="mailto:sowmya@opennms.org">Sowmya Kumaraswamy </A>
* @author <A HREF="http://www.opennms.org/">OpenNMS </A>
*/
public final class TcpEventProxy implements EventProxy {
/** Constant <code>DEFAULT_PORT=5817</code> */
public static final int DEFAULT_PORT = 5817;
/** Constant <code>DEFAULT_TIMEOUT=2000</code> */
public static final int DEFAULT_TIMEOUT = 2000;
private InetSocketAddress m_address;
private int m_timeout = DEFAULT_TIMEOUT;
/**
* <p>Constructor for TcpEventProxy.</p>
*
* @throws java.net.UnknownHostException if any.
*/
public TcpEventProxy() throws UnknownHostException {
this(new InetSocketAddress(InetAddressUtils.addr("127.0.0.1"), DEFAULT_PORT));
}
/**
* <p>Constructor for TcpEventProxy.</p>
*
* @param address a {@link java.net.InetSocketAddress} object.
*/
public TcpEventProxy(InetSocketAddress address) {
m_address = address;
}
/**
* <p>Constructor for TcpEventProxy.</p>
*
* @param address a {@link java.net.InetSocketAddress} object.
* @param timeout a int.
*/
public TcpEventProxy(InetSocketAddress address, int timeout) {
this(address);
m_timeout = timeout;
}
/**
* {@inheritDoc}
*
* This method is called to send the event out
* @exception UndeclaredThrowableException
* thrown if the send fails for any reason
*/
public void send(Event event) throws EventProxyException {
Log elog = new Log();
Events events = new Events();
events.addEvent(event);
elog.setEvents(events);
send(elog);
}
/**
* This method is called to send an event log containing multiple events
* out.
*
* @param eventLog
* the events to be sent out
* @exception UndeclaredThrowableException
* thrown if the send fails for any reason
* @throws org.opennms.netmgt.model.events.EventProxyException if any.
*/
public void send(Log eventLog) throws EventProxyException {
Connection connection = null;
try {
connection = new Connection();
final Writer writer = connection.getWriter();
JaxbUtils.marshal(eventLog, writer);
writer.flush();
} catch (ConnectException e) {
throw new EventProxyException("Could not connect to event daemon " + m_address + " to send event: " + e.getMessage(), e);
} catch (Throwable e) {
throw new EventProxyException("Unknown exception while sending event: " + e, e);
} finally {
if (connection != null) {
connection.close();
}
}
}
private ThreadCategory log() {
return ThreadCategory.getInstance(getClass());
}
private class Connection {
private Socket m_sock;
private Writer m_writer;
private InputStream m_input;
private Thread m_rdrThread;
public Connection() throws IOException {
m_sock = new Socket();
m_sock.connect(m_address, m_timeout);
m_sock.setSoTimeout(500);
log().debug("Default Charset:" + Charset.defaultCharset().displayName());
log().debug("Setting Charset: UTF-8");
m_writer = new OutputStreamWriter(new BufferedOutputStream(m_sock.getOutputStream()), Charset.forName("UTF-8"));
m_input = m_sock.getInputStream();
m_rdrThread = new Thread("TcpEventProxy Input Discarder") {
public void run() {
for (int ch = 0; ch != -1; ) {
try {
ch = m_input.read();
} catch (InterruptedIOException e) {
ch = 0;
} catch (IOException e) {
ch = -1;
}
}
}
};
m_rdrThread.setDaemon(true);
m_rdrThread.start();
}
public Writer getWriter() {
return m_writer;
}
public void close() {
if (m_sock != null) {
try {
m_sock.close();
} catch (IOException e) {
log().warn("Error closing socket " + m_sock + ": " + e, e);
}
}
m_sock = null;
if (m_rdrThread.isAlive()) {
m_rdrThread.interrupt();
}
}
protected void finalize() throws Throwable {
close();
}
}
}