aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator/service/protocol
diff options
context:
space:
mode:
authorLyubomir Marinov <lyubomir.marinov@jitsi.org>2008-09-20 20:36:27 +0000
committerLyubomir Marinov <lyubomir.marinov@jitsi.org>2008-09-20 20:36:27 +0000
commit182ada36e3a288d03fd7d6d96e88d1bb409dc983 (patch)
treedc3ecf63b2dcbcccf38c8a1018041382649629d2 /src/net/java/sip/communicator/service/protocol
parent7447c700b0414a077aff8ec7fea337dad1f4d11e (diff)
downloadjitsi-182ada36e3a288d03fd7d6d96e88d1bb409dc983.zip
jitsi-182ada36e3a288d03fd7d6d96e88d1bb409dc983.tar.gz
jitsi-182ada36e3a288d03fd7d6d96e88d1bb409dc983.tar.bz2
When starting the applications, loads the stored accounts in the background in order to allow the UI to appear as soon as possible.
Diffstat (limited to 'src/net/java/sip/communicator/service/protocol')
-rw-r--r--src/net/java/sip/communicator/service/protocol/AbstractProtocolProviderService.java12
-rw-r--r--src/net/java/sip/communicator/service/protocol/AccountManager.java61
-rw-r--r--src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java476
-rw-r--r--src/net/java/sip/communicator/service/protocol/event/AccountManagerEvent.java84
-rw-r--r--src/net/java/sip/communicator/service/protocol/event/AccountManagerListener.java31
-rw-r--r--src/net/java/sip/communicator/service/protocol/protocol.provider.manifest.mf1
6 files changed, 478 insertions, 187 deletions
diff --git a/src/net/java/sip/communicator/service/protocol/AbstractProtocolProviderService.java b/src/net/java/sip/communicator/service/protocol/AbstractProtocolProviderService.java
index 2a7334e..5d1b414 100644
--- a/src/net/java/sip/communicator/service/protocol/AbstractProtocolProviderService.java
+++ b/src/net/java/sip/communicator/service/protocol/AbstractProtocolProviderService.java
@@ -29,7 +29,8 @@ public abstract class AbstractProtocolProviderService
* A list of all listeners registered for
* <tt>RegistrationStateChangeEvent</tt>s.
*/
- private final List registrationListeners = new ArrayList();
+ private final List<RegistrationStateChangeListener> registrationListeners =
+ new ArrayList<RegistrationStateChangeListener>();
/**
* Registers the specified listener with this provider so that it would
@@ -73,16 +74,17 @@ public abstract class AbstractProtocolProviderService
logger.debug("Dispatching " + event + " to "
+ registrationListeners.size()+ " listeners.");
- Iterator listeners = null;
+ Iterator<RegistrationStateChangeListener> listeners = null;
synchronized (registrationListeners)
{
- listeners = new ArrayList(registrationListeners).iterator();
+ listeners =
+ new ArrayList<RegistrationStateChangeListener>(
+ registrationListeners).iterator();
}
while (listeners.hasNext())
{
- RegistrationStateChangeListener listener
- = (RegistrationStateChangeListener) listeners.next();
+ RegistrationStateChangeListener listener = listeners.next();
listener.registrationStateChanged(event);
}
diff --git a/src/net/java/sip/communicator/service/protocol/AccountManager.java b/src/net/java/sip/communicator/service/protocol/AccountManager.java
new file mode 100644
index 0000000..6cdb8e3
--- /dev/null
+++ b/src/net/java/sip/communicator/service/protocol/AccountManager.java
@@ -0,0 +1,61 @@
+/*
+ * 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.service.protocol;
+
+import net.java.sip.communicator.service.protocol.event.*;
+
+/**
+ * Represents a manager of accounts which contains the details about the format
+ * in which the accounts in question are stored (i.e. knows how to store and load
+ * them) and takes care of loading them on start-up.
+ *
+ * @author Lubomir Marinov
+ */
+public interface AccountManager
+{
+
+ /**
+ * Registers a specific listener to be notified about events fired by this
+ * <code>AccountManager</code>. If the <code>listener</code> is already
+ * registered, it will not be registered again.
+ *
+ * @param listener the listener to be registered for notification events
+ * fired by this <code>AccountManager</code>
+ */
+ void addListener(AccountManagerListener listener);
+
+ /**
+ * Determines whether the account store represented by this manager contains
+ * stored accounts.
+ *
+ * @return <tt>true</tt> if the account store represented by this manager
+ * contains stored accounts; <tt>false</tt>, otherwise
+ */
+ boolean hasStoredAccounts();
+
+ /**
+ * Unregisters a specific listener from this <code>AccountManager</code> so
+ * that it no longer received notifications about events fired by this
+ * manager.
+ *
+ * @param listener the listener to be unregistered from this
+ * <code>AccountManager</code> so that it no longer receives
+ * notifications about events fired by this manager
+ */
+ void removeListener(AccountManagerListener listener);
+
+ /**
+ * Stores an account represented in the form of an <code>AccountID</code>
+ * created by a specific <code>ProtocolProviderFactory</code>.
+ *
+ * @param factory the <code>ProtocolProviderFactory</code> which created the
+ * account to be stored
+ * @param accountID the account in the form of <code>AccountID</code> to be
+ * stored
+ */
+ void storeAccount(ProtocolProviderFactory factory, AccountID accountID);
+}
diff --git a/src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java b/src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java
index 3501cd5..82fdb82 100644
--- a/src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java
+++ b/src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java
@@ -8,13 +8,11 @@ package net.java.sip.communicator.service.protocol;
import java.util.*;
+import org.osgi.framework.*;
-import net.java.sip.communicator.impl.protocol.sip.*;
import net.java.sip.communicator.service.configuration.*;
import net.java.sip.communicator.util.*;
-import org.osgi.framework.*;
-
/**
* The ProtocolProviderFactory is what actually creates instances of a
* ProtocolProviderService implementation. A provider factory would register,
@@ -25,6 +23,7 @@ import org.osgi.framework.*;
* would user account registered through the various services.
*
* @author Emil Ivov
+ * @author Lubomir Marinov
*/
public abstract class ProtocolProviderFactory
{
@@ -202,6 +201,48 @@ public abstract class ProtocolProviderFactory
public static final String IS_PROTOCOL_HIDDEN = "IS_PROTOCOL_HIDDEN";
/**
+ * The <code>BundleContext</code> containing (or to contain) the service
+ * registration of this factory.
+ */
+ private final BundleContext bundleContext;
+
+ /**
+ * The name of the protocol this factory registers its
+ * <code>ProtocolProviderService</code>s with and to be placed in the
+ * properties of the accounts created by this factory.
+ */
+ private final String protocolName;
+
+ /**
+ * The table that we store our accounts in.
+ * <p>
+ * TODO Synchronize the access to the field which may in turn be better
+ * achieved by also hiding it from protected into private access.
+ * </p>
+ */
+ protected final Hashtable<AccountID, ServiceRegistration> registeredAccounts =
+ new Hashtable<AccountID, ServiceRegistration>();
+
+ protected ProtocolProviderFactory(BundleContext bundleContext,
+ String protocolName)
+ {
+ this.bundleContext = bundleContext;
+ this.protocolName = protocolName;
+ }
+
+ /**
+ * Gets the <code>BundleContext</code> containing (or to contain) the
+ * service registration of this factory.
+ *
+ * @return the <code>BundleContext</code> containing (or to contain) the
+ * service registration of this factory
+ */
+ public BundleContext getBundleContext()
+ {
+ return bundleContext;
+ }
+
+ /**
* Initializes and creates an account corresponding to the specified
* accountProperties and registers the resulting ProtocolProvider in the
* <tt>context</tt> BundleContext parameter. Note that account
@@ -254,7 +295,13 @@ public abstract class ProtocolProviderFactory
* @return a copy of the list containing the <tt>AccountID</tt>s of all
* accounts currently registered in this protocol provider.
*/
- public abstract ArrayList<AccountID> getRegisteredAccounts();
+ public ArrayList<AccountID> getRegisteredAccounts()
+ {
+ synchronized (registeredAccounts)
+ {
+ return new ArrayList<AccountID>(registeredAccounts.keySet());
+ }
+ }
/**
* Returns the ServiceReference for the protocol provider corresponding to
@@ -264,8 +311,17 @@ public abstract class ProtocolProviderFactory
* specified account id and null if the account id is unknown to the
* provider factory.
*/
- public abstract ServiceReference getProviderForAccount(
- AccountID accountID);
+ public ServiceReference getProviderForAccount(AccountID accountID)
+ {
+ ServiceRegistration registration;
+
+ synchronized (registeredAccounts)
+ {
+ registration =
+ (ServiceRegistration) registeredAccounts.get(accountID);
+ }
+ return (registration == null) ? null : registration.getReference();
+ }
/**
* Removes the specified account from the list of accounts that this
@@ -279,121 +335,103 @@ public abstract class ProtocolProviderFactory
* @return true if an account with the specified ID existed and was removed
* and false otherwise.
*/
- public abstract boolean uninstallAccount(AccountID accountID);
-
- /**
- * The method stores the specified account in the configuration service
- * under the package name of the source factory. The restore and remove
- * account methods are to be used to obtain access to and control the stored
- * accounts.
- * <p>
- * In order to store all account properties, the method would create an
- * entry in the configuration service corresponding (beginning with) the
- * <tt>sourceFactory</tt>'s package name and add to it a unique identifier
- * (e.g. the current miliseconds.)
- * <p>
- * @param bundleContext a currently valid bundle context.
- * @param accountID the AccountID corresponding to the account that we would
- * like to store.
- */
- protected void storeAccount(BundleContext bundleContext,
- AccountID accountID)
+ public boolean uninstallAccount(AccountID accountID)
{
- String sourcePackageName = getFactoryImplPackageName();
-
- String accountNodeName = null;
-
- ServiceReference confReference
- = bundleContext.getServiceReference(
- ConfigurationService.class.getName());
-
- ConfigurationService configurationService
- = (ConfigurationService) bundleContext.getService(confReference);
+ // Unregister the protocol provider.
+ ServiceReference serRef = getProviderForAccount(accountID);
- // First check if such accountID already exist in the configuration.
- List accounts = configurationService
- .getPropertyNamesByPrefix(sourcePackageName, true);
-
- Iterator accountsIter = accounts.iterator();
-
- while(accountsIter.hasNext())
+ if (serRef == null)
{
- String accountRootPropName
- = (String) accountsIter.next();
+ return false;
+ }
- String accountIDString
- = configurationService.getString(
- accountRootPropName + ".ACCOUNT_UID");
+ BundleContext bundleContext = getBundleContext();
+ ProtocolProviderService protocolProvider =
+ (ProtocolProviderService) bundleContext.getService(serRef);
- if(accountIDString.equals(accountID.getAccountUniqueID()))
- {
- accountNodeName
- = configurationService.getString(accountRootPropName);
- }
+ try
+ {
+ protocolProvider.unregister();
}
-
- //Create a unique node name of the properties node that will contain
- //this account's properties.
- if (accountNodeName == null)
+ catch (OperationFailedException ex)
{
- accountNodeName = "acc" + Long.toString(System.currentTimeMillis());
-
- //set a value for the persistent node so that we could later
- // retrieve it as a property
- configurationService.setProperty(
- sourcePackageName //prefix
- + "." + accountNodeName,
- accountNodeName);
-
- //register the account in the configuration service.
- //we register all the properties in the following hierarchy
- //net.java.sip.communicator.impl.protocol.PROTO_NAME.ACC_ID.PROP_NAME
- configurationService.setProperty(
- sourcePackageName//prefix
- + "." + accountNodeName // node name for the account id
- + "." + ACCOUNT_UID, // propname
- accountID.getAccountUniqueID()); // value
+ logger
+ .error("Failed to unregister protocol provider for account : "
+ + accountID + " caused by: " + ex);
}
- //store the rest of the properties
- Iterator accountPropKeys
- = accountID.getAccountProperties().keySet().iterator();
+ ServiceRegistration registration;
- while (accountPropKeys.hasNext())
+ synchronized (registeredAccounts)
{
- String propKey =
- (String)accountPropKeys.next();
- String propValue =
- (String)accountID.getAccountProperties().get(propKey);
+ registration = registeredAccounts.remove(accountID);
+ }
+ if (registration == null)
+ {
+ return false;
+ }
- //if this is a password - encode it.
- if(propKey.equals(PASSWORD))
- propValue = new String(Base64.encode(propValue.getBytes()));
+ // Kill the service.
+ registration.unregister();
- configurationService.setProperty(
- sourcePackageName //prefix
+ return removeStoredAccount(bundleContext, accountID);
+ }
- + "." + accountNodeName // a uniew node name for the account id
- + "." + propKey, // propname
- propValue); // value
- }
+ /**
+ * The method stores the specified account in the configuration service
+ * under the package name of the source factory. The restore and remove
+ * account methods are to be used to obtain access to and control the stored
+ * accounts.
+ * <p>
+ * In order to store all account properties, the method would create an
+ * entry in the configuration service corresponding (beginning with) the
+ * <tt>sourceFactory</tt>'s package name and add to it a unique identifier
+ * (e.g. the current miliseconds.)
+ * </p>
+ *
+ * @param accountID the AccountID corresponding to the account that we would
+ * like to store.
+ */
+ protected void storeAccount(AccountID accountID)
+ {
+ getAccountManager().storeAccount(this, accountID);
+ }
- logger.debug("Stored account for id " + accountID.getAccountUniqueID()
- + " for package " + getFactoryImplPackageName());
+ /**
+ * Saves the password for the specified account after scrambling it a bit so
+ * that it is not visible from first sight. (The method remains highly
+ * insecure).
+ *
+ * @param accountID the AccountID for the account whose password we're
+ * storing
+ * @param password the password itself
+ *
+ * @throws IllegalArgumentException if no account corresponding to
+ * <code>accountID</code> has been previously stored
+ */
+ public void storePassword(AccountID accountID, String password)
+ throws IllegalArgumentException
+ {
+ storePassword(getBundleContext(), accountID, password);
}
/**
* Saves the password for the specified account after scrambling it a bit
- * sot that it is not visible from first sight (Method remains highly
+ * so that it is not visible from first sight (Method remains highly
* insecure).
- *
+ * <p>
+ * TODO Delegate the implementation to {@link AccountManager} because it
+ * knows the format in which the password (among the other account
+ * properties) is to be saved.
+ * </p>
+ *
* @param bundleContext a currently valid bundle context.
* @param accountID the AccountID for the account whose password we're
- * storing.
+ * storing.
* @param password the password itself.
- *
- * @throws java.lang.IllegalArgumentException if no account corresponding
- * to <tt>accountID</tt> has been previously stored.
+ *
+ * @throws IllegalArgumentException if no account corresponding to
+ * <tt>accountID</tt> has been previously stored.
*/
protected void storePassword(BundleContext bundleContext,
AccountID accountID,
@@ -431,11 +469,29 @@ public abstract class ProtocolProviderFactory
/**
* Returns the password last saved for the specified account.
- *
+ *
+ * @param accountID the AccountID for the account whose password we're
+ * looking for
+ *
+ * @return a String containing the password for the specified accountID
+ */
+ public String loadPassword(AccountID accountID)
+ {
+ return loadPassword(getBundleContext(), accountID);
+ }
+
+ /**
+ * Returns the password last saved for the specified account.
+ * <p>
+ * TODO Delegate the implementation to {@link AccountManager} because it
+ * knows the format in which the password (among the other account
+ * properties) was saved.
+ * </p>
+ *
* @param bundleContext a currently valid bundle context.
* @param accountID the AccountID for the account whose password we're
- * looking for..
- *
+ * looking for..
+ *
* @return a String containing the password for the specified accountID.
*/
protected String loadPassword(BundleContext bundleContext,
@@ -465,103 +521,110 @@ public abstract class ProtocolProviderFactory
return new String(Base64.decode(mangledPassword));
}
-
/**
- * Restores all accounts stored for the package corresponding to
- * sourceFactory and and installs everyone of them through the install
- * account method.
- * <p>
- * @param bundleContext a currently valid bundle context.
+ * Initializes and creates an account corresponding to the specified
+ * accountProperties and registers the resulting ProtocolProvider in the
+ * <tt>context</tt> BundleContext parameter. This method has a persistent
+ * effect. Once created the resulting account will remain installed until
+ * removed through the uninstallAccount method.
+ *
+ * @param accountProperties a set of protocol (or implementation) specific
+ * properties defining the new account.
+ * @return the AccountID of the newly loaded account
*/
- protected void loadStoredAccounts(BundleContext bundleContext)
+ public AccountID loadAccount(Map accountProperties)
{
- String sourcePackageName = getFactoryImplPackageName();
+ BundleContext bundleContext = getBundleContext();
+ if (bundleContext == null)
+ throw new NullPointerException(
+ "The specified BundleContext was null");
- ServiceReference confReference
- = bundleContext.getServiceReference(
- ConfigurationService.class.getName());
- ConfigurationService configurationService
- = (ConfigurationService) bundleContext.getService(confReference);
+ if (accountProperties == null)
+ throw new NullPointerException(
+ "The specified property map was null");
- //first retrieve all accounts that we've registered
- List storedAccounts = configurationService.getPropertyNamesByPrefix(
- sourcePackageName, true);
-
- logger.debug("Discovered "
- + storedAccounts.size()
- + " stored accounts");
+ String userID = (String) accountProperties.get(USER_ID);
+ if (userID == null)
+ throw new NullPointerException(
+ "The account properties contained no user id.");
- //load all accounts stored in the configuration service
- Iterator storedAccountsIter = storedAccounts.iterator();
+ String protocolName = getProtocolName();
+ if (!accountProperties.containsKey(PROTOCOL))
+ accountProperties.put(PROTOCOL, protocolName);
- while (storedAccountsIter.hasNext())
- {
- String accountRootPropName = (String) storedAccountsIter.next();
- logger.debug("Loading account " + accountRootPropName);
+ AccountID accountID = createAccountID(userID, accountProperties);
- //get all properties that we've stored for this account and load
- //them into the accountProperties table.
+ ProtocolProviderService service = createService(userID, accountID);
- List storedAccPropNames = configurationService.getPropertyNamesByPrefix(
- accountRootPropName, true);
+ Dictionary<String, String> properties = new Hashtable<String, String>();
+ properties.put(PROTOCOL, protocolName);
+ properties.put(USER_ID, userID);
- Iterator propNamesIter = storedAccPropNames.iterator();
- Map accountProperties = new Hashtable();
- while(propNamesIter.hasNext())
- {
- String fullPropertyName = (String)propNamesIter.next();
- String storedPropertyValue
- = configurationService.getString(fullPropertyName);
+ ServiceRegistration serviceRegistration =
+ bundleContext.registerService(ProtocolProviderService.class
+ .getName(), service, properties);
- //strip the package prefix off the property name.
- String propertyName = fullPropertyName.substring(
- fullPropertyName.lastIndexOf('.')+1);
+ synchronized (registeredAccounts)
+ {
+ registeredAccounts.put(accountID, serviceRegistration);
+ }
- //if this is a password - decode it first
- if(propertyName.equals(PASSWORD))
- {
- if(storedPropertyValue == null
- || storedPropertyValue.length() == 0)
- {
- storedPropertyValue = "";
- }
- else
- {
- storedPropertyValue = new String(
- Base64.decode(storedPropertyValue));
- }
- }
+ return accountID;
+ }
- if(storedPropertyValue != null)
- accountProperties.put(propertyName, storedPropertyValue);
- }
- try
- {
- loadAccount(accountProperties);
- }
- catch (Exception exc)
- {
- //catch any exception here so that one failing accoung does not
- //cut the whole account reloading process
- logger.error("Failed to reload account:" + accountProperties,
- exc);
- }
- }
+ /**
+ * Creates a new <code>AccountID</code> instance with a specific user ID to
+ * represent a given set of account properties.
+ * <p>
+ * The method is a pure factory allowing implementers to specify the runtime
+ * type of the created <code>AccountID</code> and customize the instance.
+ * The returned <code>AccountID</code> will later be associated with a
+ * <code>ProtocolProviderService</code> by the caller (e.g. using
+ * {@link #createService(String, AccountID)}).
+ * </p>
+ *
+ * @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
+ */
+ protected abstract AccountID createAccountID(String userID,
+ Map accountProperties);
+
+ /**
+ * Gets the name of the protocol this factory registers its
+ * <code>ProtocolProviderService</code>s with and to be placed in the
+ * properties of the accounts created by this factory.
+ *
+ * @return the name of the protocol this factory registers its
+ * <code>ProtocolProviderService</code>s with and to be placed in
+ * the properties of the accounts created by this factory
+ */
+ protected String getProtocolName()
+ {
+ return protocolName;
}
/**
- * Initializes and creates an account corresponding to the specified
- * accountProperties and registers the resulting ProtocolProvider in the
- * <tt>context</tt> BundleContext parameter. This method has a persistent
- * effect. Once created the resulting account will remain installed until
- * removed through the uninstall account method.
- *
- * @param accountProperties a set of protocol (or implementation)
- * specific properties defining the new account.
- *
- * @return the AccountID of the newly loaded account
- */
- protected abstract AccountID loadAccount( Map accountProperties);
+ * Initializes a new <code>ProtocolProviderService</code> instance with a
+ * specific user ID to represent a specific <code>AccountID</code>.
+ * <p>
+ * The method is a pure factory allowing implementers to specify the runtime
+ * type of the created <code>ProtocolProviderService</code> and customize
+ * the instance. The caller will later register the returned service with
+ * the <code>BundleContext</code> of this factory.
+ * </p>
+ *
+ * @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>
+ */
+ protected abstract ProtocolProviderService createService(String userID,
+ AccountID accountID);
/**
* Removes the account with <tt>accountID</tt> from the set of accounts
@@ -691,4 +754,53 @@ public abstract class ProtocolProviderFactory
return className.substring(0, className.lastIndexOf('.'));
}
+
+ /**
+ * Prepares the factory for bundle shutdown.
+ */
+ public void stop()
+ {
+ logger.trace("Preparing to stop all protocol providers of" + this);
+
+ synchronized (registeredAccounts)
+ {
+ for (Enumeration<ServiceRegistration> registrations =
+ registeredAccounts.elements(); registrations.hasMoreElements();)
+ {
+ ServiceRegistration reg = registrations.nextElement();
+
+ stop(reg);
+
+ reg.unregister();
+ }
+
+ registeredAccounts.clear();
+ }
+ }
+
+ /**
+ * Shuts down the <code>ProtocolProviderService</code> representing an
+ * account registered with this factory.
+ *
+ * @param registeredAccount the <code>ServiceRegistration</code> of the
+ * <code>ProtocolProviderService</code> representing an account
+ * registered with this factory
+ */
+ protected void stop(ServiceRegistration registeredAccount)
+ {
+ ProtocolProviderService protocolProviderService =
+ (ProtocolProviderService) getBundleContext().getService(
+ registeredAccount.getReference());
+
+ protocolProviderService.shutdown();
+ }
+
+ private AccountManager getAccountManager()
+ {
+ BundleContext bundleContext = getBundleContext();
+ ServiceReference serviceReference =
+ bundleContext.getServiceReference(AccountManager.class.getName());
+
+ return (AccountManager) bundleContext.getService(serviceReference);
+ }
}
diff --git a/src/net/java/sip/communicator/service/protocol/event/AccountManagerEvent.java b/src/net/java/sip/communicator/service/protocol/event/AccountManagerEvent.java
new file mode 100644
index 0000000..550b340
--- /dev/null
+++ b/src/net/java/sip/communicator/service/protocol/event/AccountManagerEvent.java
@@ -0,0 +1,84 @@
+/*
+ * 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.service.protocol.event;
+
+import java.util.*;
+
+import net.java.sip.communicator.service.protocol.*;
+
+/**
+ * Represents a notifying event fired by a specific {@link AccountManager}.
+ *
+ * @author Lubomir Marinov
+ */
+public class AccountManagerEvent
+ extends EventObject
+{
+
+ /**
+ * The type of event notifying that the loading of the stored accounts of a
+ * specific <code>ProtocolProviderFactory</code> has finished.
+ */
+ public static final int STORED_ACCOUNTS_LOADED = 1;
+
+ /**
+ * The <code>ProtocolProviderFactory</code> being worked on at the time this
+ * event has been fired.
+ */
+ private final ProtocolProviderFactory factory;
+
+ /**
+ * The (detail) type of this event which is one of
+ * {@link #STORED_ACCOUNTS_LOADED}.
+ */
+ private final int type;
+
+ /**
+ * Initializes a new <code>AccountManagerEvent</code> instance fired by a
+ * specific <code>AccountManager</code> in order to notify of an event of a
+ * specific type occurring while working on a specific
+ * <code>ProtocolProviderFactory</code>.
+ *
+ * @param accountManager the <code>AccountManager</code> issuing the
+ * notification i.e. the source of the event
+ * @param type
+ * @param factory the <code>ProtocolProviderFactory</code> being worked on
+ * at the time this event has been fired
+ */
+ public AccountManagerEvent(AccountManager accountManager, int type,
+ ProtocolProviderFactory factory)
+ {
+ super(accountManager);
+
+ this.type = type;
+ this.factory = factory;
+ }
+
+ /**
+ * Gets the <code>ProtocolProviderFactory</code> being worked on at the time
+ * this event has been fired.
+ *
+ * @return the <code>ProtocolProviderFactory</code> being worked on at the
+ * time this event has been fired
+ */
+ public ProtocolProviderFactory getFactory()
+ {
+ return factory;
+ }
+
+ /**
+ * Gets the (detail) type of this event which is one of
+ * <code>STORED_ACCOUNTS_LOADED</code>.
+ *
+ * @return the (detail) type of this event which is one of
+ * <code>STORED_ACCOUNTS_LOADED</code>
+ */
+ public int getType()
+ {
+ return type;
+ }
+}
diff --git a/src/net/java/sip/communicator/service/protocol/event/AccountManagerListener.java b/src/net/java/sip/communicator/service/protocol/event/AccountManagerListener.java
new file mode 100644
index 0000000..ee03822
--- /dev/null
+++ b/src/net/java/sip/communicator/service/protocol/event/AccountManagerListener.java
@@ -0,0 +1,31 @@
+/*
+ * 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.service.protocol.event;
+
+import java.util.*;
+
+import net.java.sip.communicator.service.protocol.*;
+
+/**
+ * Represents a listener receiving notifications from {@link AccountManager}.
+ *
+ * @author Lubomir Marinov
+ */
+public interface AccountManagerListener
+ extends EventListener
+{
+
+ /**
+ * Notifies this listener about an event fired by a specific
+ * <code>AccountManager</code>.
+ *
+ * @param event the <code>AccountManagerEvent</code> describing the
+ * <code>AccountManager</code> firing the notification and the
+ * other details of the specific notification.
+ */
+ void handleAccountManagerEvent(AccountManagerEvent event);
+}
diff --git a/src/net/java/sip/communicator/service/protocol/protocol.provider.manifest.mf b/src/net/java/sip/communicator/service/protocol/protocol.provider.manifest.mf
index 557bd2b..c2faf0c 100644
--- a/src/net/java/sip/communicator/service/protocol/protocol.provider.manifest.mf
+++ b/src/net/java/sip/communicator/service/protocol/protocol.provider.manifest.mf
@@ -1,3 +1,4 @@
+Bundle-Activator: net.java.sip.communicator.impl.protocol.ProtocolProviderActivator
Bundle-Name: Protocol Provider Service
Bundle-Description: Protocol Provider Service.
Bundle-Vendor: sip-communicator.org