| /******************************************************************************* |
| * 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.osgi.framework.Bundle; |
| import org.osgi.service.packageadmin.PackageAdmin; |
| 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() { |
| PackageAdmin admin = Activator.getDefault().getPackageAdmin(); |
| Bundle[] bundles = admin.getBundles( |
| "org.eclipse.ecf.provider.datashare.nio", null); //$NON-NLS-1$ |
| return bundles != null && bundles.length != 0; |
| } |
| |
| /** |
| * 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$ |
| 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) { |
| // TODO Auto-generated method stub |
| |
| } |
| |
| public Object getAdapter(Class adapter) { |
| // TODO Auto-generated method stub |
| 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; |
| } |
| |
| } |