/*
* RHQ Management Platform
* Copyright (C) 2005-2011 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation, and/or the GNU Lesser
* General Public License, version 2.1, also as published by the Free
* Software Foundation.
*
* This program 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 and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with this program;
* if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.rhq.plugins.platform.win;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.sigar.win32.EventLog;
import org.hyperic.sigar.win32.EventLogRecord;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.event.Event;
import org.rhq.core.domain.event.EventSeverity;
import org.rhq.core.pluginapi.event.EventPoller;
/**
* A delegate for reading windows event logs and returning them as RHQ events. Supports
* filtering by regular expression of the content, as well as minimum severity.
*
* @author Greg Hinkle, Jay Shaughnessy
*/
public class Win32EventLogDelegate implements EventPoller {
private static final String EVENT_TYPE = "Event Log";
private final Log log = LogFactory.getLog(Win32EventLogDelegate.class);
private String[] logNames;
private EventLog[] eventLogs;
private int[] lastCollectedEventId;
private EventSeverity minimumSeverity;
private Pattern regularExpression;
private int eventsChecked;
private int eventsFired;
public Win32EventLogDelegate(Configuration config) {
this.logNames = EventLog.getLogNames();
String minimumSeverityString = config.getSimpleValue("minimumSeverity", "Error");
if ("Information".equals(minimumSeverityString)) {
minimumSeverity = EventSeverity.INFO;
} else if ("Warning".equals(minimumSeverityString)) {
minimumSeverity = EventSeverity.WARN;
} else if ("Error".equals(minimumSeverityString)) {
minimumSeverity = EventSeverity.ERROR;
}
String regexString = config.getSimpleValue("regularExpression", null);
try {
if (regexString != null) {
regularExpression = Pattern.compile(regexString);
}
} catch (PatternSyntaxException pse) {
log.warn("Event tracking regular expression not valid, no filtering will take place", pse);
}
eventLogs = new EventLog[logNames.length];
lastCollectedEventId = new int[logNames.length];
}
public void open() {
for (int i = 0; i < eventLogs.length; i++) {
try {
if (eventLogs[i] == null) {
eventLogs[i] = new EventLog();
eventLogs[i].open(logNames[i]);
// note, the first processed event will be the next one generated, this one
// was generated in the past, prior to this call to open().
lastCollectedEventId[i] = eventLogs[i].getNewestRecord();
}
} catch (Exception e) {
log.warn("Failed to open Windows Event Log [" + logNames[i] + "]; will not collect its events", e);
eventLogs[i] = null;
}
}
}
public void close() {
for (int i = 0; i < eventLogs.length; i++) {
try {
if (eventLogs[i] != null) {
eventLogs[i].close();
eventLogs[i] = null;
}
} catch (Exception e) {
log.warn("Failed to close Windows Event Log [" + logNames[i] + "]", e);
}
}
}
@Nullable
public Set<Event> checkForNewEvents() {
Set<Event> convertedEvents = null;
for (int i = 0; i < eventLogs.length; i++) {
try {
if (eventLogs[i] != null) {
int newest = eventLogs[i].getNewestRecord();
if (newest > lastCollectedEventId[i]) {
for (int eventId = lastCollectedEventId[i] + 1; eventId <= newest; eventId++) {
eventsChecked++;
EventLogRecord event = eventLogs[i].read(eventId);
Event convertedEvent = handleEvent(event);
if (null != convertedEvent) {
if (null == convertedEvents) {
convertedEvents = new HashSet<Event>();
}
convertedEvents.add(convertedEvent);
}
}
lastCollectedEventId[i] = newest;
}
}
} catch (Exception e) {
log.info("An error occurred while reading the Windows Event Log [" + logNames[i] + "]", e);
}
}
return convertedEvents;
}
public Event handleEvent(EventLogRecord event) {
if (regularExpression != null) {
if (!regularExpression.matcher(event.getMessage()).find()) {
return null;
}
}
if (!convertSeverity(event.getEventType()).isAtLeastAsSevereAs(minimumSeverity)) {
return null;
}
Event convertedEvent = new Event(EVENT_TYPE, event.getLogName(), event.getTimeGenerated() * 1000,
convertSeverity(event.getEventType()), event.getMessage());
eventsFired++;
return convertedEvent;
}
private EventSeverity convertSeverity(short type) {
switch (type) {
case EventLog.EVENTLOG_INFORMATION_TYPE:
return EventSeverity.INFO;
case EventLog.EVENTLOG_WARNING_TYPE:
return EventSeverity.WARN;
case EventLog.EVENTLOG_ERROR_TYPE:
return EventSeverity.ERROR;
default:
return EventSeverity.DEBUG;
}
}
@NotNull
public String getEventType() {
return EVENT_TYPE;
}
@Nullable
public Set<Event> poll() {
return checkForNewEvents();
}
public int getEventsChecked() {
return eventsChecked;
}
public int getEventsFired() {
return eventsFired;
}
}