/******************************************************************************* * Copyright (c) 2004, 2009 Composent, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Composent, Inc. - initial API and implementation * Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bug 197604, 197329 ******************************************************************************/ package org.eclipse.ecf.internal.provider.irc.container; import java.net.InetSocketAddress; import java.util.*; import org.eclipse.ecf.core.*; import org.eclipse.ecf.core.events.*; import org.eclipse.ecf.core.identity.*; import org.eclipse.ecf.core.security.IConnectContext; import org.eclipse.ecf.core.util.ECFException; import org.eclipse.ecf.internal.provider.irc.Activator; import org.eclipse.ecf.internal.provider.irc.Messages; import org.eclipse.ecf.internal.provider.irc.datashare.IIRCDatashareContainer; import org.eclipse.ecf.internal.provider.irc.datashare.IRCDatashareContainer; import org.eclipse.ecf.internal.provider.irc.identity.IRCID; import org.eclipse.ecf.internal.provider.irc.identity.IRCNamespace; import org.eclipse.ecf.presence.chatroom.*; import org.eclipse.ecf.presence.history.IHistory; import org.eclipse.ecf.presence.history.IHistoryManager; import org.eclipse.ecf.presence.im.IChatMessage.Type; import org.eclipse.ecf.presence.im.IChatMessageSender; import org.eclipse.equinox.concurrent.future.TimeoutException; import org.eclipse.osgi.util.NLS; import org.schwering.irc.lib.*; import org.schwering.irc.lib.ssl.SSLIRCConnection; /** * IRC 'root' container implementation. This class implements the * IChatRoomManager and the IChatRoomContainer interfaces, allowing it to * function as both a manager of IRC channels and as an IRC channel itself. * */ public class IRCRootContainer extends IRCAbstractContainer implements IContainer, IChatMessageSender, IChatRoomInvitationSender, IChatRoomManager, IChatRoomContainer, IRCMessageChannel, IChatRoomContainerOptionsAdapter { private static final long CONNECT_TIMEOUT = new Long(System.getProperty( "org.eclipse.ecf.provider.irc.connectTimeout", "60000")) .longValue(); protected IRCConnection connection = null; protected ReplyHandler replyHandler = null; protected Map channels = new HashMap(); protected String username; protected String encoding = null; private ArrayList invitationListeners; protected Object connectLock = new Object(); protected boolean connectWaiting = false; protected Exception connectException = null; /** * The datashare container implementation owned by this container. */ private IIRCDatashareContainer datashareContainer; /** * Used for determining whether the USERHOST reply should be hijacked or * not. */ private boolean retrieveUserhost; public IRCRootContainer(ID localID) throws IDCreateException { this.localID = localID; this.unknownID = IDFactory.getDefault().createStringID( Messages.IRCRootContainer_0); this.replyHandler = new ReplyHandler(); invitationListeners = new ArrayList(); datashareContainer = createDatashareContainer(); } /** * Creates and returns a datashare container implementation. * * @return a datashare container implementation for this container, or * <code>null</code> if it could not be created */ private IIRCDatashareContainer createDatashareContainer() { if (hasDatashare() && hasNIO()) { return new IRCDatashareContainer(this); } return null; } /** * Checks and returns whether the datashare NIO APIs are available in the * current OSGi environment. * * @return <code>true</code> if the datashare NIO APIs are available, * <code>false</code> otherwise */ private boolean hasDatashare() { return Activator.getDefault().hasDatashare(); } /** * Checks and returns there is Java 1.4 NIO support in the current Java * runtime environment. * * @return <code>true</code> if the Java 1.4 NIO APIs are available, * <code>false</code> otherwise */ private boolean hasNIO() { try { Class.forName("java.nio.channels.SocketChannel"); //$NON-NLS-1$ return true; } catch (ClassNotFoundException e) { return false; } } /* * (non-Javadoc) * * @see * org.eclipse.ecf.core.IContainer#connect(org.eclipse.ecf.core.identity.ID, * org.eclipse.ecf.core.security.IConnectContext) */ public void connect(ID connectID, IConnectContext connectContext) throws ContainerConnectException { if (connection != null) throw new ContainerConnectException( Messages.IRCRootContainer_Exception_Already_Connected); if (connectID == null) throw new ContainerConnectException( Messages.IRCRootContainer_Exception_TargetID_Null); if (!(connectID instanceof IRCID)) throw new ContainerConnectException(NLS.bind( Messages.IRCRootContainer_Exception_TargetID_Wrong_Type, new Object[] { targetID, IRCID.class.getName() })); if (connectWaiting) throw new ContainerConnectException( Messages.IRCRootContainer_Connecting); fireContainerEvent(new ContainerConnectingEvent(this.getID(), connectID, connectContext)); // Get password via callback in connectContext String pw = getPasswordFromConnectContext(connectContext); IRCID tID = (IRCID) connectID; String host = tID.getHost(); int port = tID.getPort(); String pass = pw; String nick = tID.getUser(); String user = nick; this.username = user; String name = null; boolean ssl = false; if (!ssl) { connection = new IRCConnection(host, new int[] { port }, pass, nick, user, name); } else { connection = new SSLIRCConnection(host, new int[] { port }, pass, nick, user, name); } // connection setup connection.addIRCEventListener(getIRCEventListener()); connection.setPong(true); connection.setDaemon(false); connection.setColors(true); if (encoding != null) connection.setEncoding(encoding); trace(Messages.IRCRootContainer_Connecting_To + targetID); synchronized (connectLock) { connectWaiting = true; connectException = null; try { connection.connect(); long timeout = CONNECT_TIMEOUT + System.currentTimeMillis(); while (connectWaiting && (timeout > System.currentTimeMillis())) { connectLock.wait(2000); } if (connectWaiting) throw new TimeoutException(NLS.bind( Messages.IRCRootContainer_Connect_Timeout, tID.getName()), CONNECT_TIMEOUT); if (connectException != null) throw connectException; this.targetID = tID; fireContainerEvent(new ContainerConnectedEvent(getID(), this.targetID)); if (datashareContainer != null) { // now that we've connected successfully, we send a USERHOST // message to the server so that we can attempt to retrieve // our current IP retrieveUserhost = true; connection.doUserhost(nick); } } catch (Exception e) { this.targetID = null; throw new ContainerConnectException(NLS.bind( Messages.IRCRootContainer_Exception_Connect_Failed, connectID.getName()), e); } finally { connectWaiting = false; connectException = null; } } } protected void handleDisconnected() { for (Iterator i = channels.values().iterator(); i.hasNext();) { IRCChannelContainer c = (IRCChannelContainer) i.next(); c.disconnect(); } fireContainerEvent(new ContainerDisconnectedEvent(getID(), targetID)); channels.clear(); } protected void handleErrorIfConnecting(String message) { synchronized (connectLock) { if (connectWaiting) this.connectException = new Exception(message); } } protected IRCEventListener getIRCEventListener() { return new IRCEventListener() { public void onRegistered() { trace("handleOnRegistered()"); //$NON-NLS-1$ synchronized (connectLock) { connectWaiting = false; connectLock.notify(); } } public void onDisconnected() { trace("handleOnDisconnected()"); //$NON-NLS-1$ fireContainerEvent(new ContainerDisconnectingEvent(getID(), targetID)); synchronized (connectLock) { if (connectWaiting) { if (connectException == null) connectException = new Exception( Messages.IRCRootContainer_Exception_Unexplained_Disconnect); connectWaiting = false; connectLock.notify(); } } if (targetID != null) { showMessage(null, NLS.bind( Messages.IRCRootContainer_Disconnected, targetID.getName())); handleDisconnected(); } } public void onError(String arg0) { trace("handleOnError(" + arg0 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ showMessage(null, NLS.bind(Messages.IRCRootContainer_Error, arg0)); handleErrorIfConnecting(arg0); } public void onError(int arg0, String arg1) { String msg = arg0 + "," + arg1; //$NON-NLS-1$ trace("handleOnError(" + msg + ")"); //$NON-NLS-1$ //$NON-NLS-2$ showMessage(null, NLS.bind(Messages.IRCRootContainer_Error, msg)); handleErrorIfConnecting(arg0 + msg); } public void onInvite(String arg0, IRCUser arg1, String arg2) { handleInvite(createIDFromString(arg0), createIDFromString(arg1.getNick())); } public void onJoin(String arg0, IRCUser arg1) { trace("handleOnJoin(" + arg0 + "," + arg1 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ IRCChannelContainer container = getChannel(arg0); if (container != null) { container.setIRCUser(arg1); } } public void onKick(String channelName, IRCUser kicker, String kicked, String reason) { trace("handleOnKick(" + channelName + "," + kicker + "," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + kicked + "," + reason + ")"); //$NON-NLS-1$ //$NON-NLS-2$ // retrieve the channel that this kick is happening at IRCChannelContainer channel = getChannel(channelName); if (channel != null) { // display a message to indicate that a user has been kicked // from the channel showMessage(channelName, NLS.bind( Messages.IRCRootContainer_UserKicked, new Object[] { kicker.getNick(), kicked, channelName, reason })); // check if we are the ones that have been kicked if (kicked.equals(((IRCID) targetID).getUsername())) { // fire disconnection events for this channel container channel.fireContainerEvent(new ContainerDisconnectingEvent( channel.getID(), channel.targetID)); channel.firePresenceListeners(false, new String[] { kicked }); channel.fireContainerEvent(new ContainerDisconnectedEvent( channel.getID(), channel.targetID)); } else { channel.firePresenceListeners(false, new String[] { kicked }); } } } public void onMode(String arg0, IRCUser arg1, IRCModeParser arg2) { trace("handleOnMode(" + arg0 + "," + arg1 + "," + arg2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } public void onMode(IRCUser arg0, String arg1, String arg2) { trace("handleOnMode(" + arg0 + "," + arg1 + "," + arg2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } public void onNick(IRCUser arg0, String arg1) { trace("handleOnNick(" + arg0 + "," + arg1 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } public void onNotice(String arg0, IRCUser arg1, String arg2) { trace("handleOnNotice(" + arg0 + "," + arg1 + "," + arg2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ showMessage(arg0, arg2); } public void onPart(String arg0, IRCUser arg1, String arg2) { trace("handleOnPart(" + arg0 + "," + arg1 + "," + arg2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ IRCChannelContainer channel = (IRCChannelContainer) channels .get(arg0); if (channel != null) { channel.firePresenceListeners(false, new String[] { getIRCUserName(arg1) }); } } public void onPing(String arg0) { trace("handleOnPing(" + arg0 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ synchronized (IRCRootContainer.this) { if (connection != null) { connection.doPong(arg0); } } } public void onPrivmsg(String arg0, IRCUser arg1, String arg2) { trace("handleOnPrivmsg(" + arg0 + "," + arg1 + "," + arg2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ if (arg2.equals("\01VERSION\01")) { //$NON-NLS-1$ showMessage(null, NLS.bind( Messages.IRCRootContainer_CTCP_VERSION_Request, arg1.toString())); } else if (arg2.startsWith("\01ECF ") && arg2.endsWith("\01")) { //$NON-NLS-1$ //$NON-NLS-2$ if (datashareContainer != null) { // special ECF message, retrieve the ip address of the // remote peer and initiate a socket connection String identifier = arg2 .substring(5, arg2.length() - 1); StringTokenizer tokenizer = new StringTokenizer( identifier, ":"); //$NON-NLS-1$ datashareContainer.enqueue(new InetSocketAddress( tokenizer.nextToken(), Integer .parseInt(tokenizer.nextToken()))); } } else { showMessage(arg0, arg1.toString(), arg2); } } public void onQuit(IRCUser arg0, String arg1) { trace("handleOnQuit(" + arg0 + "," + arg1 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ for (Iterator i = channels.values().iterator(); i.hasNext();) { IRCChannelContainer container = (IRCChannelContainer) i .next(); container.handleUserQuit(getIRCUserName(arg0)); } } public void onReply(int arg0, String arg1, String arg2) { trace("handleOnReply(" + arg0 + "|" + arg1 + "|" + arg2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ replyHandler.handleReply(arg0, arg1, arg2); } public void onTopic(String arg0, IRCUser arg1, String arg2) { trace("handleOnTopic(" + arg0 + "," + arg1 + "," + arg2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ handleSetSubject(arg0, arg1, arg2); } public void unknown(String arg0, String arg1, String arg2, String arg3) { trace("handleUnknown(" + arg0 + "," + arg1 + "," + arg2 + "," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + arg3 + ")"); //$NON-NLS-1$ showMessage(null, NLS.bind( Messages.IRCRootContainer_Unknown_Message, new Object[] { arg0, arg1, arg2, arg3 })); } }; } protected String getIRCUserName(IRCUser user) { return user == null ? null : user.toString(); } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainer#disconnect() */ public void disconnect() { if (connection != null) { connection.close(); connection = null; targetID = null; retrieveUserhost = false; } } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainer#getAdapter(java.lang.Class) */ public Object getAdapter(Class serviceType) { if (serviceType == null) { return null; } else if (serviceType.isInstance(this)) { return this; } else if (datashareContainer != null && serviceType.isInstance(datashareContainer)) { return datashareContainer; } return null; } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainer#getConnectNamespace() */ public Namespace getConnectNamespace() { return IDFactory.getDefault().getNamespaceByName( IRCNamespace.IRC_SCHEME); } public IChatRoomInfo getChatRoomInfo(final String roomName) { if (roomName == null) return new IChatRoomInfo() { public IChatRoomContainer createChatRoomContainer() throws ContainerCreateException { return IRCRootContainer.this; } public ID getConnectedID() { return IRCRootContainer.this.getConnectedID(); } public String getDescription() { return ""; //$NON-NLS-1$ } public String getName() { return ROOT_ROOMNAME; } public int getParticipantsCount() { return 0; } public ID getRoomID() { return getSystemID(); } public String getSubject() { return ""; //$NON-NLS-1$ } public boolean isModerated() { return false; } public boolean isPersistent() { return false; } public boolean requiresPassword() { return false; } public Object getAdapter(Class adapter) { return null; } }; return new IChatRoomInfo() { public IChatRoomContainer createChatRoomContainer() throws ContainerCreateException { try { IRCChannelContainer newChannelContainer = new IRCChannelContainer( IRCRootContainer.this, IDFactory.getDefault() .createGUID()); addChannel(roomName, newChannelContainer); return newChannelContainer; } catch (Exception e) { throw new ContainerCreateException( Messages.IRCRootContainer_Exception_Create_ChatRoom, e); } } public ID getConnectedID() { return IRCRootContainer.this.getConnectedID(); } public String getDescription() { return ""; //$NON-NLS-1$ } public String getName() { return roomName; } public int getParticipantsCount() { return 0; } public ID getRoomID() { return createIDFromString(roomName); } public String getSubject() { return ""; //$NON-NLS-1$ } public boolean isModerated() { return false; } public boolean isPersistent() { return false; } public boolean requiresPassword() { return false; } public Object getAdapter(Class adapter) { return null; } }; } public IChatRoomInfo[] getChatRoomInfos() { return new IChatRoomInfo[0]; } public IChatRoomManager[] getChildren() { return new IChatRoomManager[0]; } public IChatRoomManager getParent() { return null; } public void addChatRoomParticipantListener( IChatRoomParticipantListener participantListener) { // for root container, no participant listening } public void removeChatRoomParticipantListener( IChatRoomParticipantListener participantListener) { // for root container, no participant listening } public IChatRoomMessageSender getChatRoomMessageSender() { return new IChatRoomMessageSender() { public void sendMessage(String message) throws ECFException { if (isCommand(message)) parseCommandAndSend(message, null, null); else showErrorMessage(null, NLS.bind( Messages.IRCRootContainer_Command_Error, message, COMMAND_PREFIX)); } }; } /** * Returns string from the buffer beginning up to nearest COMMAND_DELIM. * Strips trailing COMMAND_DELIMs. * * @param buffer * @return String up to first COMMAND_DELIM occurrence in buffer. */ protected String nextToken(StringBuffer buffer) { if (buffer.length() == 0) { return null; } String token; int index = buffer.indexOf(COMMAND_DELIM); if (index == -1) { // no delim until the end of buffer token = buffer.toString(); buffer.delete(0, buffer.length()); return token; } token = buffer.substring(0, index); /* * if (token.length() == buffer.length()) { //index = token.length() - * 1; } */ // trim trailing command delims while ((buffer.length() > index) && (buffer.indexOf(COMMAND_DELIM, index) == index)) { index += COMMAND_DELIM.length(); } if (index > 0) { buffer.delete(0, index); } return token; } protected void parseCommandAndSend(String commandMessage, String channelName, String ircUser) { synchronized (this) { if (connection != null) { try { String lowerCase = commandMessage.toLowerCase(); StringBuffer command = new StringBuffer(commandMessage); if (lowerCase.startsWith("/msg ")) { //$NON-NLS-1$ commandMessage = commandMessage.substring(5); int index = commandMessage.indexOf(COMMAND_DELIM); if (index != -1) { connection.doPrivmsg( commandMessage.substring(0, index), commandMessage.substring(index + 1)); } } else if (lowerCase.startsWith("/privmsg ")) { //$NON-NLS-1$ commandMessage = commandMessage.substring(9); int index = commandMessage.indexOf(COMMAND_DELIM); if (index != -1) { connection.doPrivmsg( commandMessage.substring(0, index), commandMessage.substring(index + 1)); } } else if (lowerCase.startsWith("/op ")) { //$NON-NLS-1$ nextToken(command); // skip command String nick = nextToken(command); if (nick != null) { connection.doMode(channelName, "+o " + nick); //$NON-NLS-1$ } } else if (lowerCase.startsWith("/dop ")) { //$NON-NLS-1$ nextToken(command); // skip command String nick = nextToken(command); if (nick != null) { connection.doMode(channelName, "-o " + nick); //$NON-NLS-1$ } } else if (lowerCase.startsWith("/ban ")) { //$NON-NLS-1$ nextToken(command); // skip command String nick = nextToken(command); if (nick != null) { connection.doMode(channelName, "+b " + nick); //$NON-NLS-1$ } } else if (lowerCase.startsWith("/unban ")) { //$NON-NLS-1$ nextToken(command); // skip command String nick = nextToken(command); if (nick != null) { connection.doMode(channelName, "-b " + nick); //$NON-NLS-1$ } } else if (lowerCase.startsWith("/kick ")) { //$NON-NLS-1$ nextToken(command); // skip command String nick = nextToken(command); if (nick.startsWith("#")) { //$NON-NLS-1$ channelName = nick; nick = nextToken(command); } String comment = command.toString(); // rest of command if (comment.length() > 0) { connection.doKick(channelName, nick, comment); } else { connection.doKick(channelName, nick); } } else if (lowerCase.startsWith("/mode ")) { //$NON-NLS-1$ commandMessage = commandMessage.substring(6); int index = commandMessage.indexOf(COMMAND_DELIM); if (index != -1) { connection.doMode(channelName, commandMessage); } } else if (lowerCase.startsWith("/me ")) { //$NON-NLS-1$ nextToken(command); // skip command String message = command.toString(); if (message.length() > 0) { message = "\01ACTION " + message + "\01"; //$NON-NLS-1$ //$NON-NLS-2$ connection.doPrivmsg(channelName, message); showMessage(channelName, ircUser, message); } } else { String[] tokens = parseCommandTokens(commandMessage); handleCommandMessage(tokens, channelName); } } catch (Exception e) { showErrorMessage(channelName, NLS.bind( Messages.IRCRootContainer_Exception_Parse, new Object[] { e.getClass().getName(), e.getLocalizedMessage() })); traceStack(e, "PARSE ERROR: " + commandMessage); //$NON-NLS-1$ } } else { trace("parseMessageAndSend(" + commandMessage //$NON-NLS-1$ + ") Not connected for IRCContainer " + getID()); //$NON-NLS-1$ } } } private synchronized void handleCommandMessage(String[] tokens, String channelName) { // Look at first one and switch String origCommand = tokens[0]; String command = origCommand; while (command.startsWith(COMMAND_PREFIX)) command = command.substring(1); String[] args = new String[tokens.length - 1]; System.arraycopy(tokens, 1, args, 0, tokens.length - 1); if (command.equalsIgnoreCase(JOIN_COMMAND)) { if (args.length > 1) { connection.doJoin(args[0], args[1]); } else if (args.length > 0) { connection.doJoin(args[0]); } } else if (command.equalsIgnoreCase(LIST_COMMAND)) { if (args.length > 0) { connection.doList(args[0]); } else connection.doList(); } else if (command.equalsIgnoreCase(PART_COMMAND)) { if (args.length > 1) { connection.doPart(args[0], args[1]); } else if (args.length > 0) { connection.doPart(args[0]); } } else if (command.equalsIgnoreCase(NICK_COMMAND)) { if (args.length > 0) { connection.doNick(args[0]); } } else if (command.equalsIgnoreCase(NOTICE_COMMAND)) { if (args.length > 1) { connection.doNotice(args[0], args[1]); } } else if (command.equalsIgnoreCase(WHOIS_COMMAND)) { if (args.length > 0) { connection.doWhois(args[0]); } } else if (command.equalsIgnoreCase(QUIT_COMMAND)) { if (args.length > 0) { connection.doQuit(args[0]); } else { connection.doQuit(); } } else if (command.equalsIgnoreCase(AWAY_COMMAND)) { if (args.length > 0) { connection.doAway(args[0]); } else { connection.doAway(); } } else if (command.equalsIgnoreCase(TOPIC_COMMAND)) { if (args.length > 1) { StringBuffer sb = new StringBuffer(); for (int i = 1; i < args.length; i++) { if (i > 1) { sb.append(COMMAND_DELIM); } sb.append(args[i]); } connection.doTopic(args[0], sb.toString()); } else if (args.length > 0) { connection.doTopic(args[0]); } } else if (command.equalsIgnoreCase(INVITE_COMMAND)) { if (args.length > 1) { connection.doInvite(args[0], args[1]); } } else { String msg = NLS .bind(Messages.IRCRootContainer_Command_Unrecognized, origCommand); trace(msg + " in IRCContainer: " + getID()); //$NON-NLS-1$ showErrorMessage(channelName, msg); } } protected void handleInvite(ID channelID, ID fromID) { synchronized (invitationListeners) { for (int i = 0; i < invitationListeners.size(); i++) { IChatRoomInvitationListener icril = (IChatRoomInvitationListener) invitationListeners .get(i); icril.handleInvitationReceived(channelID, fromID, null, null); } } } protected IRCChannelContainer getChannel(String channel) { if (channel == null) return null; IRCChannelContainer container = getContainerForChannel(channel); if (container == null) return null; return container; } protected void showMessage(String channel, String msg) { IRCChannelContainer msgChannel = getChannel(channel); if (msgChannel != null) msgChannel.fireChatRoomMessageEvent(createIDFromString(channel), msg); else fireChatRoomMessageEvent((channel == null) ? getSystemID() : createIDFromString(channel), msg); } protected void showMessage(String channel, String user, String msg) { IRCChannelContainer msgChannel = getChannel(channel); if (msgChannel != null) { msgChannel.fireChatRoomMessageEvent(createIDFromString(user), msg); } else { fireChatMessageEvent(createIDFromString(user), msg); for (Iterator it = channels.values().iterator(); it.hasNext();) { msgChannel = (IRCChannelContainer) it.next(); msgChannel.fireChatMessageEvent(createIDFromString(user), msg); } } } void showErrorMessage(String channel, String msg) { IRCChannelContainer msgChannel = getChannel(channel); if (msgChannel != null) msgChannel.fireChatRoomMessageEvent( (username == null) ? getSystemID() : createIDFromString(username), msg); else fireChatRoomMessageEvent((username == null) ? getSystemID() : createIDFromString(username), msg); } ID getSystemID() { if (targetID == null) return unknownID; try { return IDFactory.getDefault().createStringID( ((IRCID) targetID).getHost()); } catch (IDCreateException e) { Activator.log( "ID creation exception in IRCContainer.getSystemID()", e); //$NON-NLS-1$ return unknownID; } } protected void handle353Reply(String channel, String[] strings) { IRCChannelContainer container = getChannel(channel); if (container == null) { showMessage(null, NLS.bind(Messages.IRCRootContainer_353_Error, channel)); } else container.firePresenceListeners(true, strings); } protected class ReplyHandler { public void handleReply(int code, String arg1, String arg2) { String[] users = parseUsers(arg1); switch (code) { case 353: handle353Reply(users[2], parseUserNames(arg2)); break; case 311: showMessage(null, NLS.bind(Messages.IRCRootContainer_Whois, users[1])); showMessage(null, trimUsername(users[2]) + "@" + users[3]); //$NON-NLS-1$ break; case 312: showMessage(null, NLS.bind(Messages.IRCRootContainer_Server, new Object[] { users[2], arg2 })); break; case 317: showMessage(null, NLS.bind(Messages.IRCRootContainer_Idle, users[2])); break; case 318: showMessage(null, Messages.IRCRootContainer_Whois_End); break; case 319: showMessage(null, NLS.bind(Messages.IRCRootContainer_Channels, arg2)); break; case 320: break; case 331: case 332: // Subject changes String[] args = parseCommandTokens(arg1); String channel = (args.length == 2) ? args[1] : ((args.length == 1) ? args[0] : null); handleSetSubject(channel, null, arg2); break; case 302: if (retrieveUserhost) { if (datashareContainer != null) { // set the retrieved ip address from the arg2 = arg2.trim(); String ip = arg2.substring(arg2.lastIndexOf('@') + 1); datashareContainer.setIP(ip); } retrieveUserhost = false; break; } default: // first user always expected to be us if (users.length < 2) showMessage(null, arg2); else { showMessage(users[1], concat(users, 2, arg2)); } } } private String trimUsername(String un) { int eq = un.indexOf('='); return un.substring(eq + 1); } } protected void handleSetSubject(String channelName, IRCUser user, String newSubject) { IRCChannelContainer channel = (IRCChannelContainer) channels .get(channelName); if (channel == null) { showMessage(null, newSubject); fireSubjectListeners(null, newSubject); } else { String nickname = (user == null) ? null : user.getNick(); ID fromID = (user == null) ? null : createIDFromString(getIRCUserName(user)); // Put out message to channel if (nickname == null) showMessage(channelName, newSubject); else showMessage(channelName, NLS.bind( Messages.IRCRootContainer_TopicChange, new Object[] { nickname, newSubject })); // Also notify subject listeners channel.fireSubjectListeners(fromID, newSubject); } } protected void doJoinChannel(String channelName, String key) { if (connection != null) { if (key == null || key.equals("")) { //$NON-NLS-1$ connection.doJoin(channelName); } else { connection.doJoin(channelName, key); } } } protected void doPartChannel(String channelName) { if (connection != null) { connection.doPart(channelName); } } protected void doSendChannelMessage(String channelName, String ircUser, String msg) { if (connection != null) { // If it's a command, if (isCommand(msg)) { parseCommandAndSend(msg, channelName, ircUser); } else { connection.doPrivmsg(channelName, msg); showMessage(channelName, ircUser, msg); } } } protected void doSendSubjectChangeMessage(String channelName, String topic) throws ECFException { if (connection == null) throw new ECFException( Messages.IRCRootContainer_Exception_Unexplained_Disconnect); connection.doTopic(channelName, topic); } protected void addChannel(String channel, IRCChannelContainer container) { channels.put(channel, container); } protected IRCChannelContainer getContainerForChannel(String channel) { return (IRCChannelContainer) channels.get(channel); } protected void removeChannel(String channel) { channels.remove(channel); } public boolean setEncoding(String encoding) { if (connection == null) { this.encoding = encoding; return true; } return false; } public void addInvitationListener(IChatRoomInvitationListener listener) { if (listener != null) { synchronized (invitationListeners) { if (!invitationListeners.contains(listener)) { invitationListeners.add(listener); } } } } public void removeInvitationListener(IChatRoomInvitationListener listener) { if (listener != null) { synchronized (invitationListeners) { invitationListeners.remove(listener); } } } /* * (non-Javadoc) * * @see * org.eclipse.ecf.presence.chatroom.IChatRoomManager#createChatRoom(java * .lang.String, java.util.Map) */ public IChatRoomInfo createChatRoom(String roomname, Map properties) throws ChatRoomCreateException { throw new ChatRoomCreateException(roomname, Messages.IRCRootContainer_Exception_Create_Not_Supported, null); } protected IHistoryManager chatRoomHistoryManager = new IHistoryManager() { public IHistory getHistory(ID chatRoomID, Map options) { // TODO Auto-generated method stub return null; } public boolean isActive() { // TODO Auto-generated method stub return false; } public void setActive(boolean active) { } public Object getAdapter(Class adapter) { return null; } }; public IHistoryManager getHistoryManager() { return chatRoomHistoryManager; } /* * (non-Javadoc) * * @see * org.eclipse.ecf.presence.chatroom.IChatRoomManager#getInvitationSender() */ public IChatRoomInvitationSender getInvitationSender() { return this; } public void sendInvitation(ID room, ID targetUser, String subject, String body) throws ECFException { if (connection == null) throw new ECFException( Messages.IRCRootContainer_EXCEPTION_CONNECTION_CANNOT_BE_NULL); connection.doInvite(targetUser.getName(), room.getName()); } public void sendChatMessage(ID toID, ID threadID, Type type, String subject, String body, Map properties) throws ECFException { sendChatMessage(toID, body); } public void sendChatMessage(ID toID, String body) throws ECFException { if (toID == null) { throw new ECFException( Messages.IRCRootContainer_EXCEPTION_TARGETID_CANNOT_BE_NULL); } // FIXME: temporary workaround to allow for the sending of messages to // users that are operators String name = toID.getName(); if (name.charAt(0) == '@') { name = name.substring(1); } connection.doPrivmsg(name, body); } public IChatMessageSender getPrivateMessageSender() { return this; } public ID[] getChatRoomParticipants() { // root channel has no participants return new ID[0]; } /* * (non-Javadoc) * * @see * org.eclipse.ecf.presence.chatroom.IChatRoomContainer#getChatRoomAdminSender * () */ public IChatRoomAdminSender getChatRoomAdminSender() { return null; } }