diff --git a/src/net/java/sip/communicator/impl/protocol/msn/OperationSetBasicInstantMessagingMsnImpl.java b/src/net/java/sip/communicator/impl/protocol/msn/OperationSetBasicInstantMessagingMsnImpl.java index 6bc3828d4..67ac7dc3f 100644 --- a/src/net/java/sip/communicator/impl/protocol/msn/OperationSetBasicInstantMessagingMsnImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/msn/OperationSetBasicInstantMessagingMsnImpl.java @@ -31,7 +31,7 @@ public class OperationSetBasicInstantMessagingMsnImpl /** * The provider that created us. */ - private ProtocolProviderServiceMsnImpl msnProvider = null; + private final ProtocolProviderServiceMsnImpl msnProvider; /** * A reference to the persistent presence operation set that we use @@ -39,7 +39,8 @@ public class OperationSetBasicInstantMessagingMsnImpl */ private OperationSetPersistentPresenceMsnImpl opSetPersPresence = null; - private OperationSetAdHocMultiUserChatMsnImpl opSetMuc = null; + private final OperationSetAdHocMultiUserChatMsnImpl opSetMuc; + /** * Creates an instance of this operation set. * @param provider a ref to the ProtocolProviderServiceImpl @@ -50,8 +51,10 @@ public class OperationSetBasicInstantMessagingMsnImpl ProtocolProviderServiceMsnImpl provider) { this.msnProvider = provider; - opSetMuc = (OperationSetAdHocMultiUserChatMsnImpl) msnProvider - .getOperationSet(OperationSetAdHocMultiUserChat.class); + opSetMuc + = (OperationSetAdHocMultiUserChatMsnImpl) + msnProvider + .getOperationSet(OperationSetAdHocMultiUserChat.class); provider.addRegistrationStateChangeListener(new RegistrationStateListener()); } @@ -83,10 +86,7 @@ public boolean isOfflineMessagingSupported() */ public boolean isContentTypeSupported(String contentType) { - if(contentType.equals(DEFAULT_MIME_TYPE)) - return true; - else - return false; + return DEFAULT_MIME_TYPE.equals(contentType); } public Message createMessage(String content, String contentType, @@ -117,10 +117,10 @@ public void sendInstantMessage(Contact to, Message message) + to); MessageDeliveredEvent msgDeliveryPendingEvt - = new MessageDeliveredEvent( - message, to, System.currentTimeMillis()); + = new MessageDeliveredEvent(message, to); - msgDeliveryPendingEvt = messageDeliveryPendingTransform(msgDeliveryPendingEvt); + msgDeliveryPendingEvt + = messageDeliveryPendingTransform(msgDeliveryPendingEvt); if (msgDeliveryPendingEvt == null) return; @@ -128,11 +128,10 @@ public void sendInstantMessage(Contact to, Message message) msnProvider.getMessenger(). sendText( ((ContactMsnImpl)to).getSourceContact().getEmail(), - msgDeliveryPendingEvt.getSourceMessage().getContent() - ); - MessageDeliveredEvent msgDeliveredEvt - = new MessageDeliveredEvent(message, to, System.currentTimeMillis()); + msgDeliveryPendingEvt.getSourceMessage().getContent()); + MessageDeliveredEvent msgDeliveredEvt + = new MessageDeliveredEvent(message, to); // msgDeliveredEvt = messageDeliveredTransform(msgDeliveredEvt); @@ -183,10 +182,14 @@ public void registrationStateChanged(RegistrationStateChangeEvent evt) (OperationSetPersistentPresenceMsnImpl) msnProvider .getOperationSet(OperationSetPersistentPresence.class); - msnProvider.getMessenger(). - addMessageListener(new MsnMessageListener()); - msnProvider.getMessenger(). - addEmailListener(new MsnMessageListener()); + MsnMessenger msnMessenger = msnProvider.getMessenger(); + + /* + * FIXME What's the point of having to MsnMessageListener + * instances? + */ + msnMessenger.addMessageListener(new MsnMessageListener()); + msnMessenger.addEmailListener(new MsnMessageListener()); } } } @@ -202,7 +205,7 @@ public void instantMessageReceived(MsnSwitchboard switchboard, // FILTER OUT THE GROUP MESSAGES if (opSetMuc.isGroupChatMessage(switchboard)) return; - + Message newMessage = createMessage(message.getContent()); Contact sourceContact = opSetPersPresence. findContactByID(contact.getEmail().getEmailAddress()); @@ -232,8 +235,7 @@ public void instantMessageReceived(MsnSwitchboard switchboard, * @param body of message * @param contentType of message * @param encoding of message - * @param displayName - * @param from the user who sent this message + * @param contact the user who sent this message */ public void offlineMessageReceived(String body, String contentType, diff --git a/src/net/java/sip/communicator/impl/protocol/msn/ProtocolProviderServiceMsnImpl.java b/src/net/java/sip/communicator/impl/protocol/msn/ProtocolProviderServiceMsnImpl.java index cfe77af64..42b2fdd89 100644 --- a/src/net/java/sip/communicator/impl/protocol/msn/ProtocolProviderServiceMsnImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/msn/ProtocolProviderServiceMsnImpl.java @@ -21,24 +21,20 @@ * An implementation of the protocol provider service over the Msn protocol * * @author Damian Minkov + * @author Lubomir Marinov */ public class ProtocolProviderServiceMsnImpl extends AbstractProtocolProviderService { - private static final Logger logger = - Logger.getLogger(ProtocolProviderServiceMsnImpl.class); + private static final Logger logger + = Logger.getLogger(ProtocolProviderServiceMsnImpl.class); private MsnMessenger messenger = null; - /** - * indicates whether or not the provider is initialized and ready for use. - */ - private boolean isInitialized = false; - /** * We use this to lock access to initialization. */ - private Object initializationLock = new Object(); + private final Object initializationLock = new Object(); /** * The identifier of the account that this provider represents. @@ -57,8 +53,15 @@ public class ProtocolProviderServiceMsnImpl /** * The icon corresponding to the msn protocol. */ - private ProtocolIconMsnImpl msnIcon - = new ProtocolIconMsnImpl(); + private final ProtocolIconMsnImpl msnIcon = new ProtocolIconMsnImpl(); + + /** + * The indicator which determines whether + * {@link MsnMessengerListener#logout(MsnMessenger)} has been received for + * {@link #messenger} and it is thus an error to call + * {@link MsnMessenger#logout()} on it. + */ + private boolean logoutReceived = false; /** * Returns the state of the registration of this protocol provider @@ -114,7 +117,8 @@ void reconnect(int reasonCode) fireRegistrationStateChanged( getRegistrationState(), RegistrationState.CONNECTION_FAILED, - RegistrationStateChangeEvent.REASON_NOT_SPECIFIED, null); + RegistrationStateChangeEvent.REASON_NOT_SPECIFIED, + null); } } @@ -130,21 +134,25 @@ private void connectAndLogin(SecurityAuthority authority, int reasonCode) synchronized(initializationLock) { //verify whether a password has already been stored for this account - String password = MsnActivator. - getProtocolProviderFactory().loadPassword(getAccountID()); + ProtocolProviderFactory protocolProviderFactory + = MsnActivator.getProtocolProviderFactory(); + AccountID accountID = getAccountID(); + String password = protocolProviderFactory.loadPassword(accountID); //decode if (password == null) { //create a default credentials object UserCredentials credentials = new UserCredentials(); - credentials.setUserName(getAccountID().getUserID()); + credentials.setUserName(accountID.getUserID()); //request a password from the user - credentials = authority.obtainCredentials( - ProtocolNames.MSN, - credentials, - reasonCode); + credentials + = authority + .obtainCredentials( + ProtocolNames.MSN, + credentials, + reasonCode); // in case user has canceled the login window if(credentials == null) @@ -152,7 +160,8 @@ private void connectAndLogin(SecurityAuthority authority, int reasonCode) fireRegistrationStateChanged( getRegistrationState(), RegistrationState.UNREGISTERED, - RegistrationStateChangeEvent.REASON_USER_REQUEST, ""); + RegistrationStateChangeEvent.REASON_USER_REQUEST, + ""); return; } @@ -165,22 +174,25 @@ private void connectAndLogin(SecurityAuthority authority, int reasonCode) fireRegistrationStateChanged( getRegistrationState(), RegistrationState.UNREGISTERED, - RegistrationStateChangeEvent.REASON_USER_REQUEST, ""); + RegistrationStateChangeEvent.REASON_USER_REQUEST, + ""); return; } password = new String(pass); if (credentials.isPasswordPersistent()) - { - MsnActivator.getProtocolProviderFactory() - .storePassword(getAccountID(), password); - } + protocolProviderFactory.storePassword(accountID, password); } - messenger = MsnMessengerFactory.createMsnMessenger( - getAccountID().getUserID(), - password); + messenger + = MsnMessengerFactory + .createMsnMessenger(accountID.getUserID(), password); + /* + * We've just created the messenger so we're sure we haven't + * received a logout for it. + */ + logoutReceived = false; messenger.addMessengerListener(new MsnConnectionListener()); persistentPresence.setMessenger(messenger); @@ -195,7 +207,8 @@ private void connectAndLogin(SecurityAuthority authority, int reasonCode) fireRegistrationStateChanged( getRegistrationState(), RegistrationState.CONNECTION_FAILED, - RegistrationStateChangeEvent.REASON_SERVER_NOT_FOUND, null); + RegistrationStateChangeEvent.REASON_SERVER_NOT_FOUND, + null); } } } @@ -216,16 +229,19 @@ void unregister(boolean fireEvent) { RegistrationState currRegState = getRegistrationState(); - if(messenger != null) - messenger.logout(); + // The synchronization is for logoutReceived at least. + synchronized (initializationLock) + { + if((messenger != null) && !logoutReceived) + messenger.logout(); + } if(fireEvent) - { fireRegistrationStateChanged( currRegState, RegistrationState.UNREGISTERED, - RegistrationStateChangeEvent.REASON_USER_REQUEST, null); - } + RegistrationStateChangeEvent.REASON_USER_REQUEST, + null); } /** @@ -254,56 +270,45 @@ public String getProtocolName() * * @see net.java.sip.communicator.service.protocol.AccountID */ - protected void initialize(String screenname, - AccountID accountID) + protected void initialize(String screenname, AccountID accountID) { synchronized(initializationLock) { this.accountID = accountID; - supportedOperationSets.put( - OperationSetInstantMessageTransform.class.getName(), + addSupportedOperationSet( + OperationSetInstantMessageTransform.class, new OperationSetInstantMessageTransformImpl()); //initialize the presence operationset persistentPresence = new OperationSetPersistentPresenceMsnImpl(this); - - supportedOperationSets.put( - OperationSetPersistentPresence.class.getName(), + addSupportedOperationSet( + OperationSetPersistentPresence.class, persistentPresence); - //register it once again for those that simply need presence - supportedOperationSets.put( OperationSetPresence.class.getName(), - persistentPresence); - - OperationSetAdHocMultiUserChat adHocMultiUserChat = - new OperationSetAdHocMultiUserChatMsnImpl(this); - - supportedOperationSets.put(OperationSetAdHocMultiUserChat.class - .getName(), adHocMultiUserChat); + addSupportedOperationSet( + OperationSetPresence.class, + persistentPresence); - // initialize the IM operation set - OperationSetBasicInstantMessagingMsnImpl basicInstantMessaging - = new OperationSetBasicInstantMessagingMsnImpl(this); + addSupportedOperationSet( + OperationSetAdHocMultiUserChat.class, + new OperationSetAdHocMultiUserChatMsnImpl(this)); - supportedOperationSets.put(OperationSetBasicInstantMessaging.class - .getName(), basicInstantMessaging); + // initialize the IM operation set + addSupportedOperationSet( + OperationSetBasicInstantMessaging.class, + new OperationSetBasicInstantMessagingMsnImpl(this)); //initialize the typing notifications operation set - typingNotifications = - new OperationSetTypingNotificationsMsnImpl(this); - - supportedOperationSets.put( - OperationSetTypingNotifications.class.getName(), + typingNotifications + = new OperationSetTypingNotificationsMsnImpl(this); + addSupportedOperationSet( + OperationSetTypingNotifications.class, typingNotifications); - OperationSetFileTransferMsnImpl fileTransferOpSet = - new OperationSetFileTransferMsnImpl(this); - supportedOperationSets.put( - OperationSetFileTransfer.class.getName(), - fileTransferOpSet); - - isInitialized = true; + addSupportedOperationSet( + OperationSetFileTransfer.class, + new OperationSetFileTransferMsnImpl(this)); } } @@ -314,28 +319,13 @@ protected void initialize(String screenname, */ public void shutdown() { - synchronized(initializationLock){ - if (messenger != null) - { - messenger.logout(); - messenger = null; - } - isInitialized = false; + synchronized(initializationLock) + { + unregister(false); + messenger = null; } } - /** - * Returns true if the provider service implementation is initialized and - * ready for use by other services, and false otherwise. - * - * @return true if the provider is initialized and ready for use and false - * otherwise - */ - public boolean isInitialized() - { - return isInitialized; - } - /** * Returns the AccountID that uniquely identifies the account represented * by this instance of the ProtocolProviderService. @@ -369,21 +359,21 @@ MsnMessenger getMessenger() * @param reason a String further explaining the reason code or null if * no such explanation is necessary. */ - public void fireRegistrationStateChanged( RegistrationState oldState, - RegistrationState newState, - int reasonCode, - String reason) + public void fireRegistrationStateChanged(RegistrationState oldState, + RegistrationState newState, + int reasonCode, + String reason) { - if(newState.equals(RegistrationState.UNREGISTERED) || - newState.equals(RegistrationState.CONNECTION_FAILED)) + if (newState.equals(RegistrationState.UNREGISTERED) + || newState.equals(RegistrationState.CONNECTION_FAILED)) messenger = null; super.fireRegistrationStateChanged(oldState, newState, reasonCode, reason); } /** - * Listens when we are logged in or out from the server - * or incoming exception in the lib impl. + * Listens when we are logged in or out from the server or incoming + * exception in the lib impl. */ private class MsnConnectionListener implements MsnMessengerListener @@ -394,18 +384,20 @@ public void loginCompleted(MsnMessenger msnMessenger) fireRegistrationStateChanged( getRegistrationState(), RegistrationState.REGISTERED, - RegistrationStateChangeEvent.REASON_NOT_SPECIFIED, null); + RegistrationStateChangeEvent.REASON_NOT_SPECIFIED, + null); } public void logout(MsnMessenger msnMessenger) { logger.trace("logout"); - unregister(true); -// if(isRegistered()) -// fireRegistrationStateChanged( -// getRegistrationState(), -// RegistrationState.UNREGISTERED, -// RegistrationStateChangeEvent.REASON_NOT_SPECIFIED, null); + + // The synchronization is for logoutReceived at least. + synchronized (initializationLock) + { + logoutReceived = true; + unregister(true); + } } public void exceptionCaught(MsnMessenger msnMessenger, @@ -446,52 +438,50 @@ else if(throwable instanceof UnknownHostException) RegistrationStateChangeEvent.REASON_SERVER_NOT_FOUND, "A network error occured. Could not connect to server."); } - else + else if(throwable instanceof MsnProtocolException) { - if(throwable instanceof MsnProtocolException) - { - MsnProtocolException exception = - (MsnProtocolException)throwable; + MsnProtocolException exception = + (MsnProtocolException)throwable; - logger.error("Error in Msn lib ", exception); + logger.error("Error in Msn lib ", exception); - switch(exception.getErrorCode()) + switch(exception.getErrorCode()) + { + case 500: + case 540: + case 601: + if(isRegistered()) { - case 500: - case 540: - case 601: - if(isRegistered()) - { - unregister(false); - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.UNREGISTERED, - RegistrationStateChangeEvent. - REASON_INTERNAL_ERROR, null); - } - break; - case 911: - if(isRegistered()) - { - unregister(false); - MsnActivator.getProtocolProviderFactory(). - storePassword(getAccountID(), null); - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.AUTHENTICATION_FAILED, - RegistrationStateChangeEvent. - REASON_AUTHENTICATION_FAILED, null); - - // We try to reconnect and ask user to retype - // password. - reconnect(SecurityAuthority.WRONG_PASSWORD); - } - break; + unregister(false); + fireRegistrationStateChanged( + getRegistrationState(), + RegistrationState.UNREGISTERED, + RegistrationStateChangeEvent.REASON_INTERNAL_ERROR, + null); } - - return; + break; + case 911: + if(isRegistered()) + { + unregister(false); + MsnActivator.getProtocolProviderFactory(). + storePassword(getAccountID(), null); + fireRegistrationStateChanged( + getRegistrationState(), + RegistrationState.AUTHENTICATION_FAILED, + RegistrationStateChangeEvent + .REASON_AUTHENTICATION_FAILED, + null); + + // We try to reconnect and ask user to retype + // password. + reconnect(SecurityAuthority.WRONG_PASSWORD); + } + break; } - + } + else + { logger.error("Error in Msn lib ", throwable); // We don't want to disconnect on any error, that's why we're diff --git a/src/net/java/sip/communicator/service/protocol/AbstractProtocolProviderService.java b/src/net/java/sip/communicator/service/protocol/AbstractProtocolProviderService.java index 9d0c1d947..c8d6fb5e4 100644 --- a/src/net/java/sip/communicator/service/protocol/AbstractProtocolProviderService.java +++ b/src/net/java/sip/communicator/service/protocol/AbstractProtocolProviderService.java @@ -12,9 +12,11 @@ import net.java.sip.communicator.util.*; /** - * Implements "standard" functionality of ProtocolProviderService in + * Implements standard functionality of ProtocolProviderService in * order to make it easier for implementers to provide complete solutions while * focusing on protocol-specific details. + * + * @author Lubomir Marinov */ public abstract class AbstractProtocolProviderService implements ProtocolProviderService @@ -55,6 +57,26 @@ public void addRegistrationStateChangeListener( } } + /** + * Adds a specific OperationSet implementation to the set of + * supported OperationSets of this instance. Serves as a type-safe + * wrapper around {@link #supportedOperationSets} and its + * {@link Hashtable#put(String, OperationSet)} and also shortens the code + * which performs such additions. + * + * @param the exact type of the OperationSet implementation to + * be added + * @param opsetClass the Class of OperationSet under the + * name of which the specified implementation is to be added + * @param opset the OperationSet implementation to be added + */ + protected void addSupportedOperationSet( + Class opsetClass, + T opset) + { + supportedOperationSets.put(opsetClass.getName(), opset); + } + /** * Creates a RegistrationStateChange event corresponding to the specified * old and new states and notifies all currently registered listeners. @@ -133,7 +155,7 @@ public void fireRegistrationStateChanged( RegistrationState oldState, @SuppressWarnings("unchecked") public T getOperationSet(Class opsetClass) { - return (T) doGetSupportedOperationSets().get(opsetClass.getName()); + return (T) supportedOperationSets.get(opsetClass.getName()); } /** @@ -165,17 +187,9 @@ public String getProtocolDisplayName() */ public Map getSupportedOperationSets() { - Map supportedOperationSets = - doGetSupportedOperationSets(); - return new Hashtable(supportedOperationSets); } - protected Map doGetSupportedOperationSets() - { - return supportedOperationSets; - } - /** * Indicates whether or not this provider is registered *