/*
* 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.sip;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
import org.osgi.framework.*;
/**
* A SIP implementation of the protocol provider factory interface.
*
* @author Emil Ivov
*/
public class ProtocolProviderFactorySipImpl
extends ProtocolProviderFactory
{
private static final Logger logger =
Logger.getLogger(ProtocolProviderFactorySipImpl.class);
/**
* Constructs a new instance of the ProtocolProviderFactorySipImpl.
*/
public ProtocolProviderFactorySipImpl()
{
super(SipActivator.getBundleContext(), ProtocolNames.SIP);
}
/**
* Initializes and creates an account corresponding to the specified
* accountProperties and registers the resulting ProtocolProvider in the
* <tt>context</tt> BundleContext parameter.
*
* @param userIDStr the user identifier uniquely representing the newly
* created account within the protocol namespace.
* @param accountProperties a set of protocol (or implementation)
* specific properties defining the new account.
* @return the AccountID of the newly created account.
* @throws IllegalArgumentException if userID does not correspond to an
* identifier in the context of the underlying protocol or if
* accountProperties does not contain a complete set of account
* installation properties.
* @throws IllegalStateException if the account has already been
* installed.
* @throws NullPointerException if any of the arguments is null.
*/
public AccountID installAccount( String userIDStr,
Map<String, String> accountProperties)
{
BundleContext context
= SipActivator.getBundleContext();
if (context == null)
throw new NullPointerException("The specified BundleContext was null");
if (userIDStr == null)
throw new NullPointerException("The specified AccountID was null");
accountProperties.put(USER_ID, userIDStr);
if (accountProperties == null)
throw new NullPointerException("The specified property map was null");
// serverAddress == null is OK because of registrarless support
String serverAddress = accountProperties.get(SERVER_ADDRESS);
if (!accountProperties.containsKey(PROTOCOL))
accountProperties.put(PROTOCOL, ProtocolNames.SIP);
AccountID accountID =
new SipAccountID(userIDStr, accountProperties, serverAddress);
//make sure we haven't seen this account id before.
if( registeredAccounts.containsKey(accountID) )
throw new IllegalStateException(
"An account for id " + userIDStr + " was already installed!");
//first store the account and only then load it as the load generates
//an osgi event, the osgi event triggers (through the UI) a call to
//the register() method and it needs to access the configuration service
//and check for a password.
this.storeAccount(accountID);
try
{
accountID = loadAccount(accountProperties);
}
catch(RuntimeException exc)
{
//it might happen that load-ing the account fails because of a bad
//initialization. if this is the case, make sure we remove it.
this.removeStoredAccount(SipActivator.getBundleContext(),
accountID);
throw exc;
}
return accountID;
}
/**
* Modifies the account corresponding to the specified accountID. This
* method is meant to be used to change properties of already existing
* accounts. Note that if the given accountID doesn't correspond to any
* registered account this method would do nothing.
*
* @param protocolProvider the protocol provider service corresponding to
* the modified account.
* @param accountProperties a set of protocol (or implementation) specific
* properties defining the new account.
*
* @throws java.lang.NullPointerException if any of the arguments is null.
*/
public void modifyAccount( ProtocolProviderService protocolProvider,
Map<String, String> accountProperties)
{
BundleContext context
= SipActivator.getBundleContext();
if (context == null)
throw new NullPointerException(
"The specified BundleContext was null");
if (protocolProvider == null)
throw new NullPointerException(
"The specified Protocol Provider was null");
SipAccountID accountID = (SipAccountID) protocolProvider.getAccountID();
// If the given accountID doesn't correspond to an existing account
// we return.
if(!registeredAccounts.containsKey(accountID))
return;
ServiceRegistration registration
= (ServiceRegistration) registeredAccounts.get(accountID);
// kill the service
if (registration != null)
registration.unregister();
if (accountProperties == null)
throw new NullPointerException(
"The specified property map was null");
// serverAddress == null is OK because of registrarless support
if (!accountProperties.containsKey(PROTOCOL))
accountProperties.put(PROTOCOL, ProtocolNames.SIP);
accountID.setAccountProperties(accountProperties);
// First store the account and only then load it as the load generates
// an osgi event, the osgi event triggers (trhgough the UI) a call to
// the register() method and it needs to acces the configuration service
// and check for a password.
this.storeAccount(accountID);
String userIDStr = accountProperties.get(USER_ID);
Hashtable<String, String> properties = new Hashtable<String, String>();
properties.put(PROTOCOL, ProtocolNames.SIP);
properties.put(USER_ID, userIDStr);
try
{
((ProtocolProviderServiceSipImpl)protocolProvider)
.initialize(userIDStr, accountID);
// We store again the account in order to store all properties added
// during the protocol provider initialization.
this.storeAccount(accountID);
registration
= context.registerService(
ProtocolProviderService.class.getName(),
protocolProvider,
properties);
registeredAccounts.put(accountID, registration);
}
catch (OperationFailedException ex)
{
logger.error("Failed to initialize account", ex);
throw new IllegalArgumentException("Failed to initialize account"
+ ex.getMessage());
}
}
/**
* Creates a new <code>SipAccountID</code> instance with a specific user
* ID to represent a given set of account properties.
*
* @param userID the user ID of the new instance
* @param accountProperties the set of properties to be represented by the
* new instance
* @return a new <code>AccountID</code> instance with the specified user ID
* representing the given set of account properties
*/
@Override
protected AccountID createAccountID(String userID, Map<String, String> accountProperties)
{
String serverAddress = accountProperties.get(SERVER_ADDRESS);
return new SipAccountID(userID, accountProperties, serverAddress);
}
/**
* Initializes a new <code>ProtocolProviderServiceSipImpl</code> instance
* with a specific user ID to represent a specific <code>AccountID</code>.
*
* @param userID the user ID to initialize the new instance with
* @param accountID the <code>AccountID</code> to be represented by the new
* instance
* @return a new <code>ProtocolProviderService</code> instance with the
* specific user ID representing the specified
* <code>AccountID</code>
*/
@Override
protected ProtocolProviderService createService(String userID,
AccountID accountID)
{
ProtocolProviderServiceSipImpl service =
new ProtocolProviderServiceSipImpl();
try
{
service.initialize(userID, (SipAccountID) accountID);
// We store again the account in order to store all properties added
// during the protocol provider initialization.
storeAccount(accountID);
}
catch (OperationFailedException ex)
{
logger.error("Failed to initialize account", ex);
throw new IllegalArgumentException("Failed to initialize account"
+ ex.getMessage());
}
return service;
}
}