/**************************************************************************** * Copyright (c) 2004, 2007 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 *****************************************************************************/ package org.eclipse.ecf.internal.provider.irc.container; import java.util.*; import org.eclipse.ecf.core.ContainerConnectException; import org.eclipse.ecf.core.events.*; import org.eclipse.ecf.core.identity.*; import org.eclipse.ecf.core.security.IConnectContext; import org.eclipse.ecf.core.user.User; import org.eclipse.ecf.core.util.ECFException; import org.eclipse.ecf.internal.provider.irc.Messages; import org.eclipse.ecf.presence.IPresence; import org.eclipse.ecf.presence.chatroom.*; 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.IRCUser; /** * IContainer class used to represent a specific IRC channel (e.g. #eclipse-dev) * */ public class IRCChannelContainer extends IRCAbstractContainer implements IChatMessageSender, IChatRoomContainer { private static final long CONNECT_TIMEOUT = new Long(System.getProperty( "org.eclipse.ecf.provider.irc.connectTimeout", "60000")) .longValue(); protected List participantListeners = new ArrayList(); protected IRCRootContainer rootContainer; protected IRCUser ircUser = null; protected String channelOperator; protected Object connectLock = new Object(); protected boolean connectWaiting = false; protected Vector channelParticipants = new Vector(); protected IChatRoomAdminSender adminSender = null; protected IChatRoomMessageSender sender = new IChatRoomMessageSender() { public void sendMessage(String message) throws ECFException { rootContainer.doSendChannelMessage(targetID.getName(), ircUser.toString(), message); } }; public IRCChannelContainer(IRCRootContainer root, ID localID) { this.rootContainer = root; this.localID = localID; } /* * (non-Javadoc) * * @seeorg.eclipse.ecf.presence.chatroom.IChatRoomContainer# * addChatParticipantListener * (org.eclipse.ecf.presence.chatroom.IChatRoomParticipantListener) */ public void addChatRoomParticipantListener( IChatRoomParticipantListener participantListener) { participantListeners.add(participantListener); } public void removeChatRoomParticipantListener( IChatRoomParticipantListener participantListener) { participantListeners.remove(participantListener); } protected void handleUserQuit(String name) { if (containsChannelParticipant(createIDFromString(name)) != null) firePresenceListeners(false, new String[] { name }); } private IPresence createPresence(final boolean available) { return new IPresence() { private static final long serialVersionUID = -7514227760059471898L; Map properties = new HashMap(); public Mode getMode() { return (available ? IPresence.Mode.AVAILABLE : IPresence.Mode.AWAY); } public Map getProperties() { return properties; } public String getStatus() { return null; } public Type getType() { return (available ? IPresence.Type.AVAILABLE : IPresence.Type.UNAVAILABLE); } public Object getAdapter(Class adapter) { return null; } public byte[] getPictureData() { return new byte[0]; } }; } protected boolean addChannelParticipant(ID participantID) { if (containsChannelParticipant(participantID) == null) { channelParticipants.add(participantID); return true; } return false; } protected ID removeChannelParticipant(ID participantID) { if (channelParticipants.remove(participantID)) return participantID; ID operatorID = createIDFromString(OPERATOR_PREFIX + participantID.getName()); if (channelParticipants.remove(operatorID)) return operatorID; return null; } protected ID containsChannelParticipant(ID participantID) { if (channelParticipants.contains(participantID)) return participantID; ID operatorID = createIDFromString(OPERATOR_PREFIX + participantID.getName()); if (channelParticipants.contains(operatorID)) return operatorID; return null; } protected void firePresenceListeners(boolean joined, String[] users) { for (int j = 0; j < users.length; j++) { if (joined) { if (isChannelOperator(users[j])) setChannelOperator(users[j]); ID participantID = createIDFromString(users[j]); if (addChannelParticipant(participantID)) { // Notify all listeners for (Iterator i = participantListeners.iterator(); i .hasNext();) { IChatRoomParticipantListener l = (IChatRoomParticipantListener) i .next(); l.handleArrived(new User(participantID)); l.handlePresenceUpdated(participantID, createPresence(true)); } } } else { ID removeID = removeChannelParticipant(createIDFromString(users[j])); if (removeID != null) { // Notify all listeners for (Iterator i = participantListeners.iterator(); i .hasNext();) { IChatRoomParticipantListener l = (IChatRoomParticipantListener) i .next(); l.handlePresenceUpdated(removeID, createPresence(false)); l.handleDeparted(new User(removeID)); } } } } } protected boolean isChannelOperator(String user) { if (user != null && user.startsWith(OPERATOR_PREFIX)) return true; return false; } /* * (non-Javadoc) * * @see * org.eclipse.ecf.presence.chatroom.IChatRoomContainer#getChatMessageSender * () */ public IChatRoomMessageSender getChatRoomMessageSender() { return sender; } protected String getIRCUserName(IRCUser user) { return user == null ? null : user.toString(); } protected void setIRCUser(IRCUser user) { if (this.ircUser == null) { this.ircUser = user; synchronized (connectLock) { if (connectWaiting) { connectWaiting = false; connectLock.notify(); } } } else firePresenceListeners(true, new String[] { getIRCUserName(user) }); } protected void fireContainerEvent(IContainerEvent event) { super.fireContainerEvent(event); } /* * (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 { // Actually do join here if (connectID == null) throw new ContainerConnectException( Messages.IRCChannelContainer_Exception_TargetID_Null); if (connectWaiting) throw new ContainerConnectException( Messages.IRCChannelContainer_Exception_Connecting); // Get channel name String channelName = connectID.getName(); fireContainerEvent(new ContainerConnectingEvent(this.getID(), connectID, connectContext)); // Get password via callback in connectContext String pw = getPasswordFromConnectContext(connectContext); synchronized (connectLock) { connectWaiting = true; try { rootContainer.doJoinChannel(channelName, pw); long timeout = CONNECT_TIMEOUT + System.currentTimeMillis(); while (connectWaiting && timeout > System.currentTimeMillis()) { connectLock.wait(2000); } if (connectWaiting) throw new TimeoutException( NLS.bind( Messages.IRCChannelContainer_Exception_Connect_Timeout, connectID.getName()), CONNECT_TIMEOUT); this.targetID = connectID; fireContainerEvent(new ContainerConnectedEvent(this.getID(), this.targetID)); } catch (Exception e) { this.targetID = null; throw new ContainerConnectException(NLS.bind( Messages.IRCChannelContainer_Exception_Connect_Failed, connectID.getName()), e); } finally { connectWaiting = false; } } } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainer#disconnect() */ public void disconnect() { fireContainerEvent(new ContainerDisconnectingEvent(getID(), targetID)); if (targetID != null) rootContainer.doPartChannel(targetID.getName()); fireContainerEvent(new ContainerDisconnectedEvent(getID(), targetID)); } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainer#getAdapter(java.lang.Class) */ public Object getAdapter(Class serviceType) { if (serviceType != null && serviceType.isInstance(this)) { return this; } return null; } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.IContainer#getConnectNamespace() */ public Namespace getConnectNamespace() { return IDFactory.getDefault().getNamespaceByName( StringID.class.getName()); } protected boolean isLocalUserChannelOperator() { return (channelOperator != null && isLocalUserChannelOperator(channelOperator)); } protected boolean isLocalUserChannelOperator(String chOperator) { if (!isChannelOperator(chOperator)) return false; String localUserName = (ircUser == null) ? null : (OPERATOR_PREFIX + ircUser.getNick()); if (localUserName == null) return false; if (chOperator.equals(localUserName)) return true; return false; } protected void setChannelOperator(String channelOperator) { this.channelOperator = channelOperator; } public void sendChatMessage(ID toID, ID threadID, org.eclipse.ecf.presence.im.IChatMessage.Type type, String subject, String body, Map properties) throws ECFException { rootContainer.sendChatMessage(toID, body); } public void sendChatMessage(ID toID, String body) throws ECFException { rootContainer.sendChatMessage(toID, body); } public IChatMessageSender getPrivateMessageSender() { return this; } public ID[] getChatRoomParticipants() { return (ID[]) channelParticipants.toArray(new ID[channelParticipants .size()]); } /* * (non-Javadoc) * * @see * org.eclipse.ecf.presence.chatroom.IChatRoomContainer#getChatRoomAdminSender * () */ public IChatRoomAdminSender getChatRoomAdminSender() { synchronized (this) { if (adminSender == null) { adminSender = new IChatRoomAdminSender() { public void sendSubjectChange(String newsubject) throws ECFException { rootContainer.doSendSubjectChangeMessage( targetID.getName(), newsubject); } }; } } return adminSender; } }