From c6563bc46d3cee2f4ed3a954cfbbb293c0676b4a Mon Sep 17 00:00:00 2001 From: Danny van Heumen Date: Sat, 16 Aug 2014 23:01:36 +0200 Subject: [PATCH] Created separate class for IRC presence management. --- .../impl/protocol/irc/IrcStack.java | 50 +---- .../impl/protocol/irc/IrcStatusEnum.java | 1 + .../impl/protocol/irc/PresenceManager.java | 201 ++++++++++++++++++ .../irc/ChatRoomMemberIrcImplTest.java | 15 +- 4 files changed, 220 insertions(+), 47 deletions(-) create mode 100644 src/net/java/sip/communicator/impl/protocol/irc/PresenceManager.java diff --git a/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java b/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java index 832dff0ae..37b1abd56 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java @@ -147,9 +147,9 @@ public class IrcStack private IIRCState connectionState; /** - * Atomic boolean containing away status. + * Manager component that manages current IRC presence. */ - private final AtomicBoolean away = new AtomicBoolean(); + private PresenceManager presence = null; /** * The cached channel list. @@ -321,6 +321,11 @@ public void onFailure(final Exception e) if (this.connectionState != null && this.connectionState.isConnected()) { + // instantiate presence manager for the connection + this.presence = + new PresenceManager(irc, this.connectionState, + this.provider.getPersistentPresence()); + // if connecting succeeded, set state to registered this.provider.setCurrentRegistrationState( RegistrationState.REGISTERED); @@ -1037,7 +1042,7 @@ public void message(final Contact contact, final Message message) */ public boolean isAway() { - return isConnected() && this.away.get(); + return isConnected() && this.presence.isAway(); } /** @@ -1052,15 +1057,7 @@ public void away(final String awayMessage) { throw new IllegalStateException("Not connected to an IRC server."); } - final IRCApi irc = this.session.get(); - if (awayMessage == null || awayMessage.isEmpty()) - { - irc.rawMessage("AWAY"); - } - else - { - irc.rawMessage("AWAY :" + awayMessage); - } + this.presence.setAway(awayMessage); } /** @@ -1170,17 +1167,6 @@ private static ChatRoomMemberRole convertMemberMode(final char modeSymbol) private final class ServerListener extends VariousMessageListenerAdapter { - /** - * Reply for acknowledging transition to available (not away any - * longer). - */ - private static final int IRC_RPL_UNAWAY = 305; - - /** - * Reply for acknowledging transition to away. - */ - private static final int IRC_RPL_NOWAWAY = 306; - /** * IRCApi instance. */ @@ -1339,24 +1325,6 @@ public void onServerNumericMessage(final ServerNumericMessage msg) .OFFLINE_MESSAGES_NOT_SUPPORTED); break; - case IRC_RPL_UNAWAY: - final IrcStatusEnum previousUnAway = - IrcStack.this.away.get() ? IrcStatusEnum.AWAY - : IrcStatusEnum.ONLINE; - IrcStack.this.away.set(false); - IrcStack.this.provider.getPersistentPresence() - .updatePresenceStatus(previousUnAway, IrcStatusEnum.ONLINE); - break; - - case IRC_RPL_NOWAWAY: - final IrcStatusEnum previousNowAway = - IrcStack.this.away.get() ? IrcStatusEnum.AWAY - : IrcStatusEnum.ONLINE; - IrcStack.this.away.set(true); - IrcStack.this.provider.getPersistentPresence() - .updatePresenceStatus(previousNowAway, IrcStatusEnum.AWAY); - break; - default: if (LOGGER.isTraceEnabled()) { diff --git a/src/net/java/sip/communicator/impl/protocol/irc/IrcStatusEnum.java b/src/net/java/sip/communicator/impl/protocol/irc/IrcStatusEnum.java index 5c0a4ab74..637ed9db7 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/IrcStatusEnum.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/IrcStatusEnum.java @@ -8,6 +8,7 @@ import java.util.*; +import net.java.sip.communicator.impl.protocol.irc.*; import net.java.sip.communicator.service.protocol.*; /** diff --git a/src/net/java/sip/communicator/impl/protocol/irc/PresenceManager.java b/src/net/java/sip/communicator/impl/protocol/irc/PresenceManager.java new file mode 100644 index 000000000..8de649d2d --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/irc/PresenceManager.java @@ -0,0 +1,201 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.protocol.irc; + +import net.java.sip.communicator.util.*; + +import com.ircclouds.irc.api.*; +import com.ircclouds.irc.api.domain.messages.*; +import com.ircclouds.irc.api.listeners.*; +import com.ircclouds.irc.api.state.*; + +/** + * Manager for presence status of IRC connection. + * + * @author Danny van Heumen + */ +public class PresenceManager +{ + /** + * Logger. + */ + private static final Logger LOGGER = Logger + .getLogger(PresenceManager.class); + + /** + * IRC client library instance. + */ + private final IRCApi irc; + + /** + * IRC client connection state. + */ + private final IIRCState state; + + /** + * Instance of OperationSetPersistentPresence for updates. + */ + private final OperationSetPersistentPresenceIrcImpl operationSet; + + /** + * Current presence status. + */ + private volatile boolean away = false; + + /** + * Active away message. + */ + private String currentMessage; + + /** + * Proposed away message. + */ + private String submittedMessage; + + /** + * Constructor. + * + * @param irc irc client library instance + * @param state irc client connection state instance + * @param operationSet OperationSetPersistentPresence irc implementation for + * handling presence changes. + */ + public PresenceManager(final IRCApi irc, final IIRCState state, + final OperationSetPersistentPresenceIrcImpl operationSet) + { + if (state == null) + { + throw new IllegalArgumentException("state cannot be null"); + } + this.state = state; + if (operationSet == null) + { + throw new IllegalArgumentException("operationSet cannot be null"); + } + this.operationSet = operationSet; + if (irc == null) + { + throw new IllegalArgumentException("irc cannot be null"); + } + irc.addListener(new PresenceListener()); + this.irc = irc; + } + + /** + * Check current Away state. + * + * @return returns true if away or false if not away + */ + public boolean isAway() + { + return this.away; + } + + /** + * Get away message. + * + * @return returns currently active away message or "" if currently not + * away. + */ + public String getMessage() + { + return this.away ? this.currentMessage : ""; + } + + /** + * Set away status and message. Disable away status by providing + * null message. + * + * @param awayMessage away message to set. If away message is null + * or empty away status will be cancelled. + */ + public void setAway(final String awayMessage) + { + if (awayMessage == null || awayMessage.isEmpty()) + { + this.irc.rawMessage("AWAY"); + } + else + { + this.submittedMessage = awayMessage; + this.irc.rawMessage("AWAY :" + awayMessage); + } + } + + /** + * Presence listener implementation for keeping track of presence changes in + * the IRC connection. + * + * @author Danny van Heumen + */ + private final class PresenceListener + extends VariousMessageListenerAdapter + { + /** + * Reply for acknowledging transition to available (not away any + * longer). + */ + private static final int IRC_RPL_UNAWAY = 305; + + /** + * Reply for acknowledging transition to away. + */ + private static final int IRC_RPL_NOWAWAY = 306; + + /** + * Presence listener constructor. + */ + private PresenceListener() + { + } + + @Override + public void onServerNumericMessage(final ServerNumericMessage msg) + { + Integer msgCode = msg.getNumericCode(); + if (msgCode == null) + { + return; + } + int code = msgCode.intValue(); + switch (code) + { + case IRC_RPL_UNAWAY: + PresenceManager.this.currentMessage = ""; + PresenceManager.this.away = false; + operationSet.updatePresenceStatus(IrcStatusEnum.AWAY, + IrcStatusEnum.ONLINE); + LOGGER.debug("Away status disabled."); + break; + case IRC_RPL_NOWAWAY: + PresenceManager.this.currentMessage = + PresenceManager.this.submittedMessage; + PresenceManager.this.away = true; + operationSet.updatePresenceStatus(IrcStatusEnum.ONLINE, + IrcStatusEnum.AWAY); + LOGGER.debug("Away status enabled."); + break; + default: + break; + } + } + + @Override + public void onUserQuit(final QuitMessage msg) + { + final String user = msg.getSource().getNick(); + if (user == null + || !user.equals(PresenceManager.this.state.getNickname())) + { + return; + } + LOGGER.debug("Local user's QUIT message received: removing " + + "presence listener."); + PresenceManager.this.irc.deleteListener(this); + } + } +} diff --git a/test/net/java/sip/communicator/impl/protocol/irc/ChatRoomMemberIrcImplTest.java b/test/net/java/sip/communicator/impl/protocol/irc/ChatRoomMemberIrcImplTest.java index e1f22cee7..43da6d179 100644 --- a/test/net/java/sip/communicator/impl/protocol/irc/ChatRoomMemberIrcImplTest.java +++ b/test/net/java/sip/communicator/impl/protocol/irc/ChatRoomMemberIrcImplTest.java @@ -212,17 +212,19 @@ public void testRemoveInsignificantRole() member.removeRole(ChatRoomMemberRole.MEMBER); Assert.assertSame(ChatRoomMemberRole.ADMINISTRATOR, member.getRole()); } - + public void testGetContact() { ChatRoom chatroom = EasyMock.createMock(ChatRoom.class); ProtocolProviderServiceIrcImpl provider = EasyMock.createMock(ProtocolProviderServiceIrcImpl.class); - OperationSetPersistentPresenceIrcImpl pp = EasyMock.createMock(OperationSetPersistentPresenceIrcImpl.class); + OperationSetPersistentPresenceIrcImpl pp = + EasyMock.createMock(OperationSetPersistentPresenceIrcImpl.class); EasyMock.expect(provider.getPersistentPresence()).andReturn(pp); EasyMock.replay(provider); - ChatRoomMemberIrcImpl member = new ChatRoomMemberIrcImpl(provider, chatroom, - "user", ChatRoomMemberRole.SILENT_MEMBER); + ChatRoomMemberIrcImpl member = + new ChatRoomMemberIrcImpl(provider, chatroom, "user", + ChatRoomMemberRole.SILENT_MEMBER); Assert.assertNull(member.getContact()); } @@ -231,8 +233,9 @@ public void testGetAvatar() ChatRoom chatroom = EasyMock.createMock(ChatRoom.class); ProtocolProviderServiceIrcImpl provider = EasyMock.createMock(ProtocolProviderServiceIrcImpl.class); - ChatRoomMemberIrcImpl member = new ChatRoomMemberIrcImpl(provider, chatroom, - "user", ChatRoomMemberRole.SILENT_MEMBER); + ChatRoomMemberIrcImpl member = + new ChatRoomMemberIrcImpl(provider, chatroom, "user", + ChatRoomMemberRole.SILENT_MEMBER); Assert.assertNull(member.getAvatar()); }