/*
* (c) Rob Gordon 2005
*/
package org.oddjob.jmx.client;
import org.apache.log4j.Logger;
import org.oddjob.logging.ArchiveNameResolver;
import org.oddjob.logging.ConsoleArchiver;
import org.oddjob.logging.LogArchiver;
import org.oddjob.logging.LogEvent;
import org.oddjob.logging.LogHelper;
import org.oddjob.logging.LogLevel;
import org.oddjob.logging.LogListener;
import org.oddjob.logging.cache.LogEventSource;
import org.oddjob.logging.cache.PollingLogArchiver;
/**
* A LogArchiver which maintains it's log archives by polling a JMX MBean for
* log information.
*
* @author Rob Gordon
*/
public class RemoteLogPoller
implements Runnable, LogArchiver, ConsoleArchiver {
private static final Logger logger = Logger.getLogger(RemoteLogPoller.class);
/** Archiver to store console messages retrieved from the server side. */
private final PollingLogArchiver consoleArchiver;
/** Archiver to store log messages retrieved from the server side. */
private final PollingLogArchiver loggerArchiver;
/** Interval between polling. */
private long logPollingInterval = 5000;
/** Stop flag */
private volatile boolean stop;
/**
* Constructor.
*
*/
public RemoteLogPoller(Object root,
final int consoleHistoryLines, final int logHistoryLines) {
if (root == null) {
throw new NullPointerException("Root component must not be null.");
}
if (consoleHistoryLines < 1) {
throw new IllegalArgumentException("Console history lines must be greater than zero.");
}
if (logHistoryLines < 1) {
throw new IllegalArgumentException("Log history lines must be greater than zero.");
}
consoleArchiver = new PollingLogArchiver(consoleHistoryLines,
new ArchiveNameResolver() {
public String resolveName(Object component) {
if (component instanceof LogPollable) {
return consoleArchiveFor((LogPollable) component);
}
else {
return null;
}
}
},
new LogEventSource() {
public LogEvent[] retrieveEvents(Object component, long last,
int max) {
logger.debug("Retrieving console events for [" + component + "]");
LogPollable pollable = (LogPollable) component;
return pollable.retrieveConsoleEvents(last, max);
}
}
);
loggerArchiver = new PollingLogArchiver(logHistoryLines,
new ArchiveNameResolver() {
public String resolveName(Object component) {
if (component instanceof LogPollable) {
return logArchiveFor((LogPollable) component);
}
else {
return null;
}
}
},
new LogEventSource() {
public LogEvent[] retrieveEvents(Object component, long last,
int max) {
LogPollable pollable = (LogPollable) component;
LogEvent[] results = pollable.retrieveLogEvents(last, max);
logger.debug("Retrieved [" + results.length + "] log events for [" + component + "]");
return results;
}
}
);
}
/**
* Utility function to get the log archive name.
*
* @return The log archive name for the given component.
*/
static String logArchiveFor(LogPollable component) {
String url = component.url();
if (url == null) {
throw new NullPointerException("[" + component + "] has no URL.");
}
String archive = LogHelper.getLogger(component);
if (archive == null) {
// Will become No Log Available.
return null;
}
return url + "#" + archive;
}
/**
* Utility function to get the console archive name.
*
* @return The console archive name for the given component.
*/
static String consoleArchiveFor(LogPollable component) {
String url = component.url();
if (url == null) {
throw new NullPointerException("Proxy for [" + component + "] has no URL.");
}
String consoleId = component.consoleId();
if (consoleId == null) {
throw new NullPointerException("Proxy for [" + component + "] has no consoleId.");
}
return url + "#" + consoleId;
}
/*
* (non-Javadoc)
* @see org.oddjob.logging.LogArchiver#addLogListener(org.oddjob.logging.LogListener, java.lang.Object, org.oddjob.logging.LogLevel, long, int)
*/
public void addLogListener(LogListener l, Object component,
LogLevel level, long last, int max) {
loggerArchiver.addLogListener(l, component, level, last, max);
synchronized (this) {
// Force a poll.
notifyAll();
}
}
/*
* (non-Javadoc)
* @see org.oddjob.logging.LogArchiver#removeLogListener(org.oddjob.logging.LogListener)
*/
public void removeLogListener(LogListener l, Object component) {
loggerArchiver.removeLogListener(l, component);
}
/* (non-Javadoc)
* @see org.oddjob.logging.ConsoleArchiver#addConsoleListener(org.oddjob.logging.LogListener, java.lang.Object, long, int)
*/
public void addConsoleListener(LogListener l, Object component, long last,
int max) {
consoleArchiver.addLogListener(l, component, LogLevel.DEBUG, last, max);
synchronized (this) {
// Force a poll.
notifyAll();
}
}
/* (non-Javadoc)
* @see org.oddjob.logging.ConsoleArchiver#removeConsoleListener(org.oddjob.logging.LogListener, java.lang.Object)
*/
public void removeConsoleListener(LogListener l, Object component) {
consoleArchiver.removeLogListener(l, component);
}
/* (non-Javadoc)
* @see org.oddjob.logging.ConsoleArchiver#consoleIdFor(java.lang.Object)
*/
public String consoleIdFor(Object component) {
return consoleArchiveFor((LogPollable) component);
}
public long getLogPollingInterval() {
return logPollingInterval;
}
public void setLogPollingInterval(long logPollingInterval) {
if (logPollingInterval == 0) {
throw new IllegalArgumentException("Log Polling Interval must be greater than zero.");
}
this.logPollingInterval = logPollingInterval;
}
/**
* Poll a remote MBean for Log Messages.
*
*/
public void poll() {
consoleArchiver.poll();
loggerArchiver.poll();
}
public void run() {
while (!stop) {
poll();
synchronized (this) {
try {
wait(logPollingInterval);
}
catch (InterruptedException e) {
return;
}
}
}
consoleArchiver.onDestroy();
loggerArchiver.onDestroy();
}
/**
* Stop polling.
*/
public void stop() {
stop = true;
synchronized (this) {
notifyAll();
}
}
public void onDestroy() {
// TODO Auto-generated method stub
}
}