mirror of https://github.com/sipwise/jitsi.git
Added multichat operation set definition and Gibberish protocol implementation. Related issues: Issue #241 , Issue #244, Issue #250
A gibberish implementation of the protocol provider servicecusax-fix
parent
b249a6c7d5
commit
72460d82df
@ -0,0 +1,402 @@
|
||||
/*
|
||||
* SIP Communicator, 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.gibberish;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.java.sip.communicator.service.protocol.*;
|
||||
import net.java.sip.communicator.service.protocol.event.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
/**
|
||||
* A Gibberish implementation of the ProtocolProviderService.
|
||||
*
|
||||
* @author Emil Ivov
|
||||
*/
|
||||
public class ProtocolProviderServiceGibberishImpl
|
||||
implements ProtocolProviderService
|
||||
{
|
||||
private static final Logger logger
|
||||
= Logger.getLogger(ProtocolProviderServiceGibberishImpl.class);
|
||||
|
||||
/**
|
||||
* The name of this protocol.
|
||||
*/
|
||||
public static final String GIBBERISH_PROTOCOL_NAME = "Gibberish";
|
||||
|
||||
/**
|
||||
* The id of the account that this protocol provider represents.
|
||||
*/
|
||||
private AccountID accountID = null;
|
||||
|
||||
/**
|
||||
* We use this to lock access to initialization.
|
||||
*/
|
||||
private Object initializationLock = new Object();
|
||||
|
||||
/**
|
||||
* The hashtable with the operation sets that we support locally.
|
||||
*/
|
||||
private Hashtable supportedOperationSets = new Hashtable();
|
||||
|
||||
/**
|
||||
* A list of listeners interested in changes in our registration state.
|
||||
*/
|
||||
private Vector registrationStateListeners = new Vector();
|
||||
|
||||
/**
|
||||
* Indicates whether or not the provider is initialized and ready for use.
|
||||
*/
|
||||
private boolean isInitialized = false;
|
||||
|
||||
/**
|
||||
* The registration state that we are currently in. Note that in a real
|
||||
* world protocol implementation this field won't exist and the registration
|
||||
* state would be retrieved from the protocol stack.
|
||||
*/
|
||||
private RegistrationState currentRegistrationState
|
||||
= RegistrationState.UNREGISTERED;
|
||||
|
||||
|
||||
/**
|
||||
* The default constructor for the Gibberish protocol provider.
|
||||
*/
|
||||
public ProtocolProviderServiceGibberishImpl()
|
||||
{
|
||||
logger.trace("Creating a gibberish provider.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the service implementation, and puts it in a sate where it
|
||||
* could interoperate with other services. It is strongly recomended that
|
||||
* properties in this Map be mapped to property names as specified by
|
||||
* <tt>AccountProperties</tt>.
|
||||
*
|
||||
* @param userID the user id of the gibberish account we're currently
|
||||
* initializing
|
||||
* @param accountID the identifier of the account that this protocol
|
||||
* provider represents.
|
||||
*
|
||||
* @see net.java.sip.communicator.service.protocol.AccountID
|
||||
*/
|
||||
protected void initialize(String userID,
|
||||
AccountID accountID)
|
||||
{
|
||||
synchronized(initializationLock)
|
||||
{
|
||||
this.accountID = accountID;
|
||||
|
||||
//initialize the presence operationset
|
||||
OperationSetPersistentPresence persistentPresence =
|
||||
new OperationSetPersistentPresenceGibberishImpl(this);
|
||||
|
||||
supportedOperationSets.put(
|
||||
OperationSetPersistentPresence.class.getName(),
|
||||
persistentPresence);
|
||||
|
||||
|
||||
//register it once again for those that simply need presence and
|
||||
//won't be smart enough to check for a persistent presence
|
||||
//alternative
|
||||
supportedOperationSets.put( OperationSetPresence.class.getName(),
|
||||
persistentPresence);
|
||||
|
||||
//initialize the IM operation set
|
||||
OperationSetBasicInstantMessagingGibberishImpl basicInstantMessaging
|
||||
= new OperationSetBasicInstantMessagingGibberishImpl(
|
||||
this
|
||||
, (OperationSetPersistentPresenceGibberishImpl)
|
||||
persistentPresence);
|
||||
|
||||
supportedOperationSets.put(
|
||||
OperationSetBasicInstantMessaging.class.getName(),
|
||||
basicInstantMessaging);
|
||||
|
||||
//initialize the typing notifications operation set
|
||||
OperationSetTypingNotifications typingNotifications =
|
||||
new OperationSetTypingNotificationsGibberishImpl(this);
|
||||
|
||||
supportedOperationSets.put(
|
||||
OperationSetTypingNotifications.class.getName(),
|
||||
typingNotifications);
|
||||
|
||||
isInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the specified listener with this provider so that it would
|
||||
* receive notifications on changes of its state or other properties such
|
||||
* as its local address and display name.
|
||||
*
|
||||
* @param listener the listener to register.
|
||||
*/
|
||||
public void addRegistrationStateChangeListener(
|
||||
RegistrationStateChangeListener listener)
|
||||
{
|
||||
synchronized(registrationStateListeners)
|
||||
{
|
||||
if (!registrationStateListeners.contains(listener))
|
||||
registrationStateListeners.add(listener);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified registration listener so that it won't receive
|
||||
* further notifications when our registration state changes.
|
||||
*
|
||||
* @param listener the listener to remove.
|
||||
*/
|
||||
public void removeRegistrationStateChangeListener(
|
||||
RegistrationStateChangeListener listener)
|
||||
{
|
||||
synchronized(registrationStateListeners)
|
||||
{
|
||||
registrationStateListeners.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <tt>RegistrationStateChangeEvent</tt> corresponding to the
|
||||
* specified old and new states and notifies all currently registered
|
||||
* listeners.
|
||||
*
|
||||
* @param oldState the state that the provider had before the change
|
||||
* occurred
|
||||
* @param newState the state that the provider is currently in.
|
||||
* @param reasonCode a value corresponding to one of the REASON_XXX fields
|
||||
* of the RegistrationStateChangeEvent class, indicating the reason for
|
||||
* this state transition.
|
||||
* @param reason a String further explaining the reason code or null if
|
||||
* no such explanation is necessary.
|
||||
*/
|
||||
private void fireRegistrationStateChanged( RegistrationState oldState,
|
||||
RegistrationState newState,
|
||||
int reasonCode,
|
||||
String reason)
|
||||
{
|
||||
RegistrationStateChangeEvent event =
|
||||
new RegistrationStateChangeEvent(
|
||||
this, oldState, newState, reasonCode, reason);
|
||||
|
||||
logger.debug("Dispatching " + event + " to "
|
||||
+ registrationStateListeners.size()+ " listeners.");
|
||||
|
||||
Iterator listeners = null;
|
||||
synchronized (registrationStateListeners)
|
||||
{
|
||||
listeners = new ArrayList(registrationStateListeners).iterator();
|
||||
}
|
||||
|
||||
while (listeners.hasNext())
|
||||
{
|
||||
RegistrationStateChangeListener listener
|
||||
= (RegistrationStateChangeListener) listeners.next();
|
||||
|
||||
listener.registrationStateChanged(event);
|
||||
}
|
||||
|
||||
logger.trace("Done.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the AccountID that uniquely identifies the account represented
|
||||
* by this instance of the ProtocolProviderService.
|
||||
*
|
||||
* @return the id of the account represented by this provider.
|
||||
*/
|
||||
public AccountID getAccountID()
|
||||
{
|
||||
return accountID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the operation set corresponding to the specified class or null
|
||||
* if this operation set is not supported by the provider implementation.
|
||||
*
|
||||
* @param opsetClass the <tt>Class</tt> of the operation set that we're
|
||||
* looking for.
|
||||
* @return returns an OperationSet of the specified <tt>Class</tt> if
|
||||
* the undelying implementation supports it or null otherwise.
|
||||
*/
|
||||
public OperationSet getOperationSet(Class opsetClass)
|
||||
{
|
||||
return (OperationSet) getSupportedOperationSets()
|
||||
.get(opsetClass.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the short name of the protocol that the implementation of this
|
||||
* provider is based upon (like SIP, Jabber, ICQ/AIM, or others for
|
||||
* example).
|
||||
*
|
||||
* @return a String containing the short name of the protocol this
|
||||
* service is implementing (most often that would be a name in
|
||||
* ProtocolNames).
|
||||
*/
|
||||
public String getProtocolName()
|
||||
{
|
||||
return GIBBERISH_PROTOCOL_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the state of the registration of this protocol provider with
|
||||
* the corresponding registration service.
|
||||
*
|
||||
* @return ProviderRegistrationState
|
||||
*/
|
||||
public RegistrationState getRegistrationState()
|
||||
{
|
||||
return currentRegistrationState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing all operation sets supported by the
|
||||
* current implementation.
|
||||
*
|
||||
* @return a java.util.Map containing instance of all supported
|
||||
* operation sets mapped against their class names (e.g.
|
||||
* OperationSetPresence.class.getName()) .
|
||||
*/
|
||||
public Map getSupportedOperationSets()
|
||||
{
|
||||
//Copy the map so that the caller is not able to modify it.
|
||||
return (Map)supportedOperationSets.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether or not this provider is registered
|
||||
*
|
||||
* @return true if the provider is currently registered and false
|
||||
* otherwise.
|
||||
*/
|
||||
public boolean isRegistered()
|
||||
{
|
||||
return currentRegistrationState.equals(RegistrationState.REGISTERED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the registration process.
|
||||
*
|
||||
* @param authority the security authority that will be used for
|
||||
* resolving any security challenges that may be returned during the
|
||||
* registration or at any moment while wer're registered.
|
||||
* @throws OperationFailedException with the corresponding code it the
|
||||
* registration fails for some reason (e.g. a networking error or an
|
||||
* implementation problem).
|
||||
*/
|
||||
public void register(SecurityAuthority authority)
|
||||
throws OperationFailedException
|
||||
{
|
||||
//we don't really need a password here since there's no server in
|
||||
//Gibberish but nevertheless we'll behave as if we did.
|
||||
|
||||
//verify whether a password has already been stored for this account
|
||||
String password = GibberishActivator.
|
||||
getProtocolProviderFactory().loadPassword(getAccountID());
|
||||
|
||||
//if we don't - retrieve it from the user through the security authority
|
||||
if (password == null)
|
||||
{
|
||||
//create a default credentials object
|
||||
UserCredentials credentials = new UserCredentials();
|
||||
credentials.setUserName(getAccountID().getUserID());
|
||||
|
||||
//request a password from the user
|
||||
credentials = authority.obtainCredentials("Gibberish"
|
||||
, credentials);
|
||||
|
||||
//extract the password the user passed us.
|
||||
char[] pass = credentials.getPassword();
|
||||
|
||||
// the user didn't provide us a password (canceled the operation)
|
||||
if (pass == null)
|
||||
{
|
||||
fireRegistrationStateChanged(
|
||||
getRegistrationState(),
|
||||
RegistrationState.UNREGISTERED,
|
||||
RegistrationStateChangeEvent.REASON_USER_REQUEST, "");
|
||||
return;
|
||||
}
|
||||
password = new String(pass);
|
||||
|
||||
//if the user indicated that the password should be saved, we'll ask
|
||||
//the proto provider factory to store it for us.
|
||||
if (credentials.isPasswordPersistent())
|
||||
{
|
||||
GibberishActivator.getProtocolProviderFactory()
|
||||
.storePassword(getAccountID(), password);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RegistrationState oldState = currentRegistrationState;
|
||||
currentRegistrationState = RegistrationState.REGISTERED;
|
||||
|
||||
fireRegistrationStateChanged(
|
||||
oldState
|
||||
, currentRegistrationState
|
||||
, RegistrationStateChangeEvent.REASON_USER_REQUEST
|
||||
, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the service implementation close all open sockets and release
|
||||
* any resources that it might have taken and prepare for
|
||||
* shutdown/garbage collection.
|
||||
*/
|
||||
public void shutdown()
|
||||
{
|
||||
if(!isInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
logger.trace("Killing the Gibberish Protocol Provider.");
|
||||
|
||||
if(isRegistered())
|
||||
{
|
||||
try
|
||||
{
|
||||
//do the unregistration
|
||||
unregister();
|
||||
}
|
||||
catch (OperationFailedException ex)
|
||||
{
|
||||
//we're shutting down so we need to silence the exception here
|
||||
logger.error(
|
||||
"Failed to properly unregister before shutting down. "
|
||||
+ getAccountID()
|
||||
, ex);
|
||||
}
|
||||
}
|
||||
|
||||
isInitialized = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the registration of this protocol provider with the current
|
||||
* registration service.
|
||||
*
|
||||
* @throws OperationFailedException with the corresponding code it the
|
||||
* registration fails for some reason (e.g. a networking error or an
|
||||
* implementation problem).
|
||||
*/
|
||||
public void unregister()
|
||||
throws OperationFailedException
|
||||
{
|
||||
RegistrationState oldState = currentRegistrationState;
|
||||
currentRegistrationState = RegistrationState.UNREGISTERED;
|
||||
|
||||
fireRegistrationStateChanged(
|
||||
oldState
|
||||
, currentRegistrationState
|
||||
, RegistrationStateChangeEvent.REASON_USER_REQUEST
|
||||
, null);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue