package org.rhq.plugins.irc; import java.util.Map; import java.util.HashMap; import java.util.Arrays; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.PropertyList; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.domain.configuration.PropertyMap; import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException; import org.rhq.core.domain.measurement.AvailabilityType; import org.rhq.core.pluginapi.inventory.ResourceComponent; import org.rhq.core.pluginapi.inventory.ResourceContext; import org.rhq.core.pluginapi.operation.OperationFacet; import org.rhq.core.pluginapi.operation.OperationResult; import org.jibble.pircbot.PircBot; /** * @author Greg Hinkle */ public class IRCServerComponent implements ResourceComponent<ResourceComponent<?>>, OperationFacet { private final Log log = LogFactory.getLog(this.getClass()); private Bot bot; private Map<String, IRCChannelComponent> channels = new HashMap<String, IRCChannelComponent>(); private String host; private String port; private String nick; private List<String> activeChannels; private Map<String, ChannelInfo> info = new HashMap<String, ChannelInfo>(); /** * Return availability of this resource * * @see org.rhq.core.pluginapi.inventory.ResourceComponent#getAvailability() */ public AvailabilityType getAvailability() { if (!this.bot.isConnected()) { try { this.bot.connect(host); } catch (Exception e) { log.warn("Failure to connect to IRC server " + host + " reason: " + e.getMessage()); } } activeChannels = Arrays.asList(this.bot.getChannels()); return this.bot.isConnected() ? AvailabilityType.UP : AvailabilityType.DOWN; } /** * Start the resource connection * * @see org.rhq.core.pluginapi.inventory.ResourceComponent#start(org.rhq.core.pluginapi.inventory.ResourceContext) */ public void start(ResourceContext context) throws InvalidPluginConfigurationException, Exception { Configuration conf = context.getPluginConfiguration(); host = conf.getSimple(IRCServerDiscoveryComponent.CONFIG_HOST).getStringValue(); port = conf.getSimple(IRCServerDiscoveryComponent.CONFIG_PORT).getStringValue(); nick = conf.getSimple(IRCServerDiscoveryComponent.CONFIG_NICK).getStringValue(); this.bot = new Bot(nick); // bot.setVerbose(true); bot.setAutoNickChange(true); bot.connect(host); } public void registerChannel(IRCChannelComponent channelComponent) { this.channels.put(channelComponent.getChannel(), channelComponent); this.bot.joinChannel(channelComponent.getChannel()); updateChannels(); } public void unregisterChannel(IRCChannelComponent channelComponent) { this.bot.partChannel(channelComponent.getChannel()); this.channels.remove(channelComponent.getChannel()); } public boolean isInChannel(String channel) { return activeChannels.contains(channel); } public void sendMessage(String channel, String message) { this.bot.sendMessage(channel, message); } public OperationResult invokeOperation(String name, Configuration parameters) throws InterruptedException, Exception { if (name.equals("listChannels")) { OperationResult result = new OperationResult(); Configuration resultConfig = result.getComplexResults(); PropertyList channelList = new PropertyList("channelList"); this.bot.listChannels(); Thread.sleep(5000); // TODO is this long enough... any other way to know when the list is done? for (ChannelInfo channelInfo : info.values()) { PropertyMap channelMap = new PropertyMap("channelMap"); channelMap.put(new PropertySimple("channel", channelInfo.channel)); channelMap.put(new PropertySimple("userCount", channelInfo.userCount)); channelMap.put(new PropertySimple("topic", channelInfo.topic)); channelList.add(channelMap); } resultConfig.put(channelList); return result; } return null; } public int getUserCount(String channel) { return this.bot.getUsers(channel).length; } public static class ChannelInfo { String channel; int userCount; String topic; public ChannelInfo(String channel, int userCount, String topic) { this.channel = channel; this.userCount = userCount; this.topic = topic; } } public class Bot extends PircBot { public Bot(String nick) { this.setName(nick); } @Override protected void onChannelInfo(String channel, int userCount, String topic) { info.put(channel, new ChannelInfo(channel, userCount, topic)); } public void onMessage(String channel, String sender, String login, String hostname, String message) { IRCChannelComponent component = IRCServerComponent.this.channels.get(channel); if (component != null) { component.acceptMessage(sender, login, hostname, message); } if (message.contains(getName()) && sender.contains("ghinkle")) { sendMessage(channel, "monitoring " + channels.size() + " channels"); } } } /** * Tear down the rescource connection * * @see org.rhq.core.pluginapi.inventory.ResourceComponent#stop() */ public void stop() { this.bot.disconnect(); } private void updateChannels() { activeChannels = Arrays.asList(this.bot.getChannels()); } }