| /**************************************************************************** |
| * 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; |
| } |
| } |