blob: f98c3c5eaa40618f5ac6ea2507898862e252c9f6 [file] [log] [blame]
/****************************************************************************
* 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;
}
}