diff options
Diffstat (limited to 'src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java')
-rw-r--r-- | src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java | 2609 |
1 files changed, 1309 insertions, 1300 deletions
diff --git a/src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java b/src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java index 7e8b9c8..561a092 100644 --- a/src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java +++ b/src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java @@ -1,4 +1,4 @@ -/*
+/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,1302 +15,1311 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.protocol;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import net.java.sip.communicator.service.credentialsstorage.*;
-import net.java.sip.communicator.util.*;
-
-import org.jitsi.service.configuration.*;
-import org.osgi.framework.*;
-
-/**
- * The ProtocolProviderFactory is what actually creates instances of a
- * ProtocolProviderService implementation. A provider factory would register,
- * persistently store, and remove when necessary, ProtocolProviders. The way
- * things are in the SIP Communicator, a user account is represented (in a 1:1
- * relationship) by an AccountID and a ProtocolProvider. In other words - one
- * would have as many protocol providers installed in a given moment as they
- * would user account registered through the various services.
- *
- * @author Emil Ivov
- * @author Lubomir Marinov
- */
-public abstract class ProtocolProviderFactory
-{
- /**
- * The <tt>Logger</tt> used by the <tt>ProtocolProviderFactory</tt> class
- * and its instances for logging output.
- */
- private static final Logger logger
- = Logger.getLogger(ProtocolProviderFactory.class);
-
- /**
- * Then name of a property which represents a password.
- */
- public static final String PASSWORD = "PASSWORD";
-
- /**
- * The name of a property representing the name of the protocol for an
- * ProtocolProviderFactory.
- */
- public static final String PROTOCOL = "PROTOCOL_NAME";
-
- /**
- * The name of a property representing the path to protocol icons.
- */
- public static final String PROTOCOL_ICON_PATH = "PROTOCOL_ICON_PATH";
-
- /**
- * The name of a property representing the path to the account icon to
- * be used in the user interface, when the protocol provider service is not
- * available.
- */
- public static final String ACCOUNT_ICON_PATH = "ACCOUNT_ICON_PATH";
-
- /**
- * The name of a property which represents the AccountID of a
- * ProtocolProvider and that, together with a password is used to login
- * on the protocol network..
- */
- public static final String USER_ID = "USER_ID";
-
- /**
- * The name that should be displayed to others when we are calling or
- * writing them.
- */
- public static final String DISPLAY_NAME = "DISPLAY_NAME";
-
- /**
- * The name that should be displayed to the user on call via and chat via
- * lists.
- */
- public static final String ACCOUNT_DISPLAY_NAME = "ACCOUNT_DISPLAY_NAME";
-
- /**
- * The name of the property under which we store protocol AccountID-s.
- */
- public static final String ACCOUNT_UID = "ACCOUNT_UID";
-
- /**
- * The name of the property under which we store protocol the address of
- * a protocol centric entity (any protocol server).
- */
- public static final String SERVER_ADDRESS = "SERVER_ADDRESS";
-
- /**
- * The name of the property under which we store the number of the port
- * where the server stored against the SERVER_ADDRESS property is expecting
- * connections to be made via this protocol.
- */
- public static final String SERVER_PORT = "SERVER_PORT";
-
- /**
- * The name of the property under which we store the name of the transport
- * protocol that needs to be used to access the server.
- */
- public static final String SERVER_TRANSPORT = "SERVER_TRANSPORT";
-
- /**
- * The name of the property under which we store protocol the address of
- * a protocol proxy.
- */
- public static final String PROXY_ADDRESS = "PROXY_ADDRESS";
-
- /**
- * The name of the property under which we store the number of the port
- * where the proxy stored against the PROXY_ADDRESS property is expecting
- * connections to be made via this protocol.
- */
- public static final String PROXY_PORT = "PROXY_PORT";
-
- /**
- * The name of the property which defines whether proxy is auto configured
- * by the protocol by using known methods such as specific DNS queries.
- */
- public static final String PROXY_AUTO_CONFIG = "PROXY_AUTO_CONFIG";
-
- /**
- * The property indicating the preferred UDP and TCP
- * port to bind to for clear communications.
- */
- public static final String PREFERRED_CLEAR_PORT_PROPERTY_NAME
- = "net.java.sip.communicator.SIP_PREFERRED_CLEAR_PORT";
-
- /**
- * The property indicating the preferred TLS (TCP)
- * port to bind to for secure communications.
- */
- public static final String PREFERRED_SECURE_PORT_PROPERTY_NAME
- = "net.java.sip.communicator.SIP_PREFERRED_SECURE_PORT";
-
- /**
- * The name of the property under which we store the the type of the proxy
- * stored against the PROXY_ADDRESS property. Exact type values depend on
- * protocols and among them are socks4, socks5, http and possibly others.
- */
- public static final String PROXY_TYPE = "PROXY_TYPE";
-
- /**
- * The name of the property under which we store the the username for the
- * proxy stored against the PROXY_ADDRESS property.
- */
- public static final String PROXY_USERNAME = "PROXY_USERNAME";
-
- /**
- * The name of the property under which we store the the authorization name
- * for the proxy stored against the PROXY_ADDRESS property.
- */
- public static final String AUTHORIZATION_NAME = "AUTHORIZATION_NAME";
-
- /**
- * The name of the property under which we store the password for the proxy
- * stored against the PROXY_ADDRESS property.
- */
- public static final String PROXY_PASSWORD = "PROXY_PASSWORD";
-
- /**
- * The name of the property under which we store the name of the transport
- * protocol that needs to be used to access the proxy.
- */
- public static final String PROXY_TRANSPORT = "PROXY_TRANSPORT";
-
- /**
- * The name of the property that indicates whether loose routing should be
- * forced for all traffic in an account, rather than routing through an
- * outbound proxy which is the default for Jitsi.
- */
- public static final String FORCE_PROXY_BYPASS = "FORCE_PROXY_BYPASS";
-
- /**
- * The name of the property that indicates whether the client must
- * be registered with a registrar when making outgoing calls.
- */
- public static final String MUST_REGISTER_TO_CALL = "MUST_REGISTER_TO_CALL";
-
- /**
- * The name of the property under which we store the user preference for a
- * transport protocol to use (i.e. tcp or udp).
- */
- public static final String PREFERRED_TRANSPORT = "PREFERRED_TRANSPORT";
-
- /**
- * The name of the property under which we store whether we generate
- * resource values or we just use the stored one.
- */
- public static final String AUTO_GENERATE_RESOURCE = "AUTO_GENERATE_RESOURCE";
-
- /**
- * The name of the property under which we store resources such as the
- * jabber resource property.
- */
- public static final String RESOURCE = "RESOURCE";
-
- /**
- * The name of the property under which we store resource priority.
- */
- public static final String RESOURCE_PRIORITY = "RESOURCE_PRIORITY";
-
- /**
- * The name of the property which defines that the call is encrypted by
- * default
- */
- public static final String DEFAULT_ENCRYPTION = "DEFAULT_ENCRYPTION";
-
- /**
- * The name of the property that indicates the encryption protocols for this
- * account.
- */
- public static final String ENCRYPTION_PROTOCOL = "ENCRYPTION_PROTOCOL";
-
- /**
- * The name of the property that indicates the status (enabed or disabled)
- * encryption protocols for this account.
- */
- public static final String ENCRYPTION_PROTOCOL_STATUS
- = "ENCRYPTION_PROTOCOL_STATUS";
-
- /**
- * The name of the property which defines if to include the ZRTP attribute
- * to SIP/SDP
- */
- public static final String DEFAULT_SIPZRTP_ATTRIBUTE =
- "DEFAULT_SIPZRTP_ATTRIBUTE";
-
- /**
- * The name of the property which defines the ID of the client TLS
- * certificate configuration entry.
- */
- public static final String CLIENT_TLS_CERTIFICATE =
- "CLIENT_TLS_CERTIFICATE";
-
- /**
- * The name of the property under which we store the boolean value
- * indicating if the user name should be automatically changed if the
- * specified name already exists. This property is meant to be used by IRC
- * implementations.
- */
- public static final String AUTO_CHANGE_USER_NAME = "AUTO_CHANGE_USER_NAME";
-
- /**
- * The name of the property under which we store the boolean value
- * indicating if a password is required. Initially this property is meant to
- * be used by IRC implementations.
- */
- public static final String NO_PASSWORD_REQUIRED = "NO_PASSWORD_REQUIRED";
-
- /**
- * The name of the property under which we store if the presence is enabled.
- */
- public static final String IS_PRESENCE_ENABLED = "IS_PRESENCE_ENABLED";
-
- /**
- * The name of the property under which we store if the p2p mode for SIMPLE
- * should be forced.
- */
- public static final String FORCE_P2P_MODE = "FORCE_P2P_MODE";
-
- /**
- * The name of the property under which we store the offline contact polling
- * period for SIMPLE.
- */
- public static final String POLLING_PERIOD = "POLLING_PERIOD";
-
- /**
- * The name of the property under which we store the chosen default
- * subscription expiration value for SIMPLE.
- */
- public static final String SUBSCRIPTION_EXPIRATION
- = "SUBSCRIPTION_EXPIRATION";
-
- /**
- * Indicates if the server address has been validated.
- */
- public static final String SERVER_ADDRESS_VALIDATED
- = "SERVER_ADDRESS_VALIDATED";
-
- /**
- * Indicates if the server settings are over
- */
- public static final String IS_SERVER_OVERRIDDEN
- = "IS_SERVER_OVERRIDDEN";
- /**
- * Indicates if the proxy address has been validated.
- */
- public static final String PROXY_ADDRESS_VALIDATED
- = "PROXY_ADDRESS_VALIDATED";
-
- /**
- * Indicates the search strategy chosen for the DICT protocole.
- */
- public static final String STRATEGY = "STRATEGY";
-
- /**
- * Indicates a protocol that would not be shown in the user interface as an
- * account.
- */
- public static final String IS_PROTOCOL_HIDDEN = "IS_PROTOCOL_HIDDEN";
-
- /**
- * Indicates if the given account is the preferred account.
- */
- public static final String IS_PREFERRED_PROTOCOL = "IS_PREFERRED_PROTOCOL";
-
- /**
- * The name of the property that would indicate if a given account is
- * currently enabled or disabled.
- */
- public static final String IS_ACCOUNT_DISABLED = "IS_ACCOUNT_DISABLED";
-
- /**
- * The name of the property that would indicate if a given account
- * configuration form is currently hidden.
- */
- public static final String IS_ACCOUNT_CONFIG_HIDDEN = "IS_CONFIG_HIDDEN";
-
- /**
- * The name of the property that would indicate if a given account
- * status menu is currently hidden.
- */
- public static final String IS_ACCOUNT_STATUS_MENU_HIDDEN =
- "IS_STATUS_MENU_HIDDEN";
-
- /**
- * The name of the property that would indicate if a given account
- * configuration is read only.
- */
- public static final String IS_ACCOUNT_READ_ONLY = "IS_READ_ONLY";
-
- /**
- * The name of the property that would indicate if a given account
- * groups are readonly, values can be all or a comma separated
- * group names including root.
- */
- public static final String ACCOUNT_READ_ONLY_GROUPS = "READ_ONLY_GROUPS";
-
- /**
- * Indicates if ICE should be used.
- */
- public static final String IS_USE_ICE = "ICE_ENABLED";
-
- /**
- * Indicates if STUN server should be automatically discovered.
- */
- public static final String AUTO_DISCOVER_STUN = "AUTO_DISCOVER_STUN";
-
- /**
- * Indicates if default STUN server would be used if no other STUN/TURN
- * server are available.
- */
- public static final String USE_DEFAULT_STUN_SERVER
- = "USE_DEFAULT_STUN_SERVER";
-
- /**
- * The name of the boolean account property which indicates whether Jitsi
- * Videobridge is to be used, if available and supported, for conference
- * calls.
- */
- public static final String USE_JITSI_VIDEO_BRIDGE
- = "USE_JITSI_VIDEO_BRIDGE";
-
- /**
- * The property name prefix for all stun server properties. We generally use
- * this prefix in conjunction with an index which is how we store multiple
- * servers.
- */
- public static final String STUN_PREFIX = "STUN";
-
- /**
- * The base property name for address of additional STUN servers specified.
- */
- public static final String STUN_ADDRESS = "ADDRESS";
-
- /**
- * The base property name for port of additional STUN servers specified.
- */
- public static final String STUN_PORT = "PORT";
-
- /**
- * The base property name for username of additional STUN servers specified.
- */
- public static final String STUN_USERNAME = "USERNAME";
-
- /**
- * The base property name for password of additional STUN servers specified.
- */
- public static final String STUN_PASSWORD = "PASSWORD";
-
- /**
- * The base property name for the turn supported property of additional
- * STUN servers specified.
- */
- public static final String STUN_IS_TURN_SUPPORTED = "IS_TURN_SUPPORTED";
-
- /**
- * Indicates if JingleNodes should be used with ICE.
- */
- public static final String IS_USE_JINGLE_NODES = "JINGLE_NODES_ENABLED";
-
- /**
- * Indicates if JingleNodes should be used with ICE.
- */
- public static final String AUTO_DISCOVER_JINGLE_NODES
- = "AUTO_DISCOVER_JINGLE_NODES";
-
- /**
- * Indicates if JingleNodes should use buddies to search for nodes.
- */
- public static final String JINGLE_NODES_SEARCH_BUDDIES
- = "JINGLE_NODES_SEARCH_BUDDIES";
-
- /**
- * Indicates if UPnP should be used with ICE.
- */
- public static final String IS_USE_UPNP = "UPNP_ENABLED";
-
- /**
- * Indicates if we allow non-TLS connection.
- */
- public static final String IS_ALLOW_NON_SECURE = "ALLOW_NON_SECURE";
-
- /**
- * Enable notifications for new voicemail messages.
- */
- public static final String VOICEMAIL_ENABLED = "VOICEMAIL_ENABLED";
-
- /**
- * Address used to reach voicemail box, by services able to
- * subscribe for voicemail new messages notifications.
- */
- public static final String VOICEMAIL_URI = "VOICEMAIL_URI";
-
- /**
- * Address used to call to hear your messages stored on the server
- * for your voicemail.
- */
- public static final String VOICEMAIL_CHECK_URI = "VOICEMAIL_CHECK_URI";
-
- /**
- * Indicates if calling is disabled for a certain account.
- */
- public static final String IS_CALLING_DISABLED_FOR_ACCOUNT
- = "CALLING_DISABLED";
-
- /**
- * Indicates if desktop streaming/sharing is disabled for a certain account.
- */
- public static final String IS_DESKTOP_STREAMING_DISABLED
- = "DESKTOP_STREAMING_DISABLED";
-
- /**
- * Indicates if desktop remote control is disabled for a certain account.
- */
- public static final String IS_DESKTOP_REMOTE_CONTROL_DISABLED
- = "DESKTOP_REMOTE_CONTROL_DISABLED";
-
- /**
- * The sms default server address.
- */
- public static final String SMS_SERVER_ADDRESS = "SMS_SERVER_ADDRESS";
-
- /**
- * Keep-alive method used by the protocol.
- */
- public static final String KEEP_ALIVE_METHOD = "KEEP_ALIVE_METHOD";
-
- /**
- * The interval for keep-alives if any.
- */
- public static final String KEEP_ALIVE_INTERVAL = "KEEP_ALIVE_INTERVAL";
-
- /**
- * The name of the property holding DTMF method.
- */
- public static final String DTMF_METHOD = "DTMF_METHOD";
-
- /**
- * The minimal DTMF tone duration.
- */
- public static final String DTMF_MINIMAL_TONE_DURATION
- = "DTMF_MINIMAL_TONE_DURATION";
-
- /**
- * Paranoia mode when turned on requires all calls to be secure and
- * indicated as such.
- */
- public static final String MODE_PARANOIA = "MODE_PARANOIA";
-
- /**
- * The name of the "override encodings" property
- */
- public static final String OVERRIDE_ENCODINGS = "OVERRIDE_ENCODINGS";
-
- /**
- * The prefix used to store account encoding properties
- */
- public static final String ENCODING_PROP_PREFIX = "Encodings";
-
- /**
- * An account property to provide a connected account to check for
- * its status. Used when the current provider need to reject calls
- * but is missing presence operation set and need to check other
- * provider for status.
- */
- public static final String CUSAX_PROVIDER_ACCOUNT_PROP
- = "cusax.XMPP_ACCOUNT_ID";
-
- /**
- * 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 Map<AccountID, ServiceRegistration<ProtocolProviderService>>
- registeredAccounts
- = new HashMap<AccountID, ServiceRegistration<ProtocolProviderService>>();
-
- /**
- * The name of the property that indicates the AVP type.
- * <ul>
- * <li>{@link #SAVP_OFF}</li>
- * <li>{@link #SAVP_MANDATORY}</li>
- * <li>{@link #SAVP_OPTIONAL}</li>
- * </ul>
- */
- public static final String SAVP_OPTION = "SAVP_OPTION";
-
- /**
- * Always use RTP/AVP
- */
- public static final int SAVP_OFF = 0;
-
- /**
- * Always use RTP/SAVP
- */
- public static final int SAVP_MANDATORY = 1;
-
- /**
- * Sends two media description, with RTP/SAVP being first.
- */
- public static final int SAVP_OPTIONAL = 2;
-
- /**
- * The name of the property that defines the enabled SDES cipher suites.
- * Enabled suites are listed as CSV by their RFC name.
- */
- public static final String SDES_CIPHER_SUITES = "SDES_CIPHER_SUITES";
-
- /**
- * The name of the property that defines the enabled/disabled state of
- * message carbons.
- */
- public static final String IS_CARBON_DISABLED = "CARBON_DISABLED";
-
- /**
- * Creates a new <tt>ProtocolProviderFactory</tt>.
- *
- * @param bundleContext the bundle context reference of the service
- * @param protocolName the name of the protocol
- */
- 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
- * registration is persistent and accounts that are registered during
- * a particular sip-communicator session would be automatically reloaded
- * during all following sessions until they are removed through the
- * removeAccount method.
- *
- * @param userID 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 java.lang.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 java.lang.IllegalStateException if the account has already been
- * installed.
- * @throws java.lang.NullPointerException if any of the arguments is null.
- */
- public abstract AccountID installAccount(String userID,
- Map<String, String> accountProperties)
- throws IllegalArgumentException,
- IllegalStateException,
- NullPointerException;
-
-
- /**
- * 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 abstract void modifyAccount(
- ProtocolProviderService protocolProvider,
- Map<String, String> accountProperties)
- throws NullPointerException;
-
- /**
- * Returns a copy of the list containing the <tt>AccountID</tt>s of all
- * accounts currently registered in this protocol provider.
- * @return a copy of the list containing the <tt>AccountID</tt>s of all
- * accounts currently registered in this protocol provider.
- */
- public ArrayList<AccountID> getRegisteredAccounts()
- {
- synchronized (registeredAccounts)
- {
- return new ArrayList<AccountID>(registeredAccounts.keySet());
- }
- }
-
- /**
- * Returns the ServiceReference for the protocol provider corresponding to
- * the specified accountID or null if the accountID is unknown.
- * @param accountID the accountID of the protocol provider we'd like to get
- * @return a ServiceReference object to the protocol provider with the
- * specified account id and null if the account id is unknown to the
- * provider factory.
- */
- public ServiceReference<ProtocolProviderService> getProviderForAccount(
- AccountID accountID)
- {
- ServiceRegistration<ProtocolProviderService> registration;
-
- synchronized (registeredAccounts)
- {
- registration = registeredAccounts.get(accountID);
- }
-
- try
- {
- if (registration != null)
- return registration.getReference();
- }
- catch (IllegalStateException ise)
- {
- synchronized (registeredAccounts)
- {
- registeredAccounts.remove(accountID);
- }
- }
-
- return null;
- }
-
- /**
- * Removes the specified account from the list of accounts that this
- * provider factory is handling. If the specified accountID is unknown to
- * the ProtocolProviderFactory, the call has no effect and false is
- * returned. This method is persistent in nature and once called the account
- * corresponding to the specified ID will not be loaded during future runs
- * of the project.
- *
- * @param accountID the ID of the account to remove.
- * @return true if an account with the specified ID existed and was removed
- * and false otherwise.
- */
- public boolean uninstallAccount(AccountID accountID)
- {
- // Unregister the protocol provider.
- ServiceReference<ProtocolProviderService> serRef
- = getProviderForAccount(accountID);
-
- boolean wasAccountExisting = false;
-
- // If the protocol provider service is registered, first unregister the
- // service.
- if (serRef != null)
- {
- BundleContext bundleContext = getBundleContext();
- ProtocolProviderService protocolProvider
- = bundleContext.getService(serRef);
-
- try
- {
- protocolProvider.unregister();
- }
- catch (OperationFailedException ex)
- {
- logger.error(
- "Failed to unregister protocol provider for account: "
- + accountID + " caused by: " + ex);
- }
- }
-
- ServiceRegistration<ProtocolProviderService> registration;
-
- synchronized (registeredAccounts)
- {
- registration = registeredAccounts.remove(accountID);
- }
-
- // first remove the stored account so when PP is unregistered we can
- // distinguish between deleted or just disabled account
- wasAccountExisting = removeStoredAccount(accountID);
-
- if (registration != null)
- {
- // Kill the service.
- registration.unregister();
- }
-
- return wasAccountExisting;
- }
-
- /**
- * 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)
- {
- this.storeAccount(accountID, true);
- }
-
- /**
- * 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.
- * @param isModification if <tt>false</tt> there must be no such already
- * loaded account, it <tt>true</tt> ist modification of an existing account.
- * Usually we use this method with <tt>false</tt> in method installAccount
- * and with <tt>true</tt> or the overridden method in method
- * modifyAccount.
- */
- protected void storeAccount(AccountID accountID, boolean isModification)
- {
- if(!isModification
- && getAccountManager().getStoredAccounts().contains(accountID))
- {
- throw new IllegalStateException(
- "An account for id " + accountID.getUserID()
- + " was already loaded!");
- }
-
- try
- {
- getAccountManager().storeAccount(this, accountID);
- }
- catch (OperationFailedException ofex)
- {
- throw new UndeclaredThrowableException(ofex);
- }
- }
-
- /**
- * 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
- {
- try
- {
- storePassword(getBundleContext(), accountID, password);
- }
- catch (OperationFailedException ofex)
- {
- throw new UndeclaredThrowableException(ofex);
- }
- }
-
- /**
- * Saves the password for the specified account after scrambling it a bit
- * 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 <tt>AccountID</tt> of the account whose password is
- * to be stored
- * @param password the password to be stored
- *
- * @throws IllegalArgumentException if no account corresponding to
- * <tt>accountID</tt> has been previously stored.
- * @throws OperationFailedException if anything goes wrong while storing the
- * specified <tt>password</tt>
- */
- protected void storePassword(BundleContext bundleContext,
- AccountID accountID,
- String password)
- throws IllegalArgumentException,
- OperationFailedException
- {
- String accountPrefix
- = findAccountPrefix(
- bundleContext,
- accountID,
- getFactoryImplPackageName());
-
- if (accountPrefix == null)
- {
- throw
- new IllegalArgumentException(
- "No previous records found for account ID: "
- + accountID.getAccountUniqueID()
- + " in package"
- + getFactoryImplPackageName());
- }
-
- CredentialsStorageService credentialsStorage
- = ServiceUtils.getService(
- bundleContext,
- CredentialsStorageService.class);
-
- if (!credentialsStorage.storePassword(accountPrefix, password))
- {
- throw
- new OperationFailedException(
- "CredentialsStorageService failed to storePassword",
- OperationFailedException.GENERAL_ERROR);
- }
-
- // Update password property also in the AccountID
- // to prevent it from being removed during account reload
- // in some cases.
- accountID.setPassword(password);
-
- }
-
- /**
- * 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..
- *
- * @return a String containing the password for the specified accountID.
- */
- protected String loadPassword(BundleContext bundleContext,
- AccountID accountID)
- {
- String accountPrefix = findAccountPrefix(
- bundleContext, accountID, getFactoryImplPackageName());
-
- if (accountPrefix == null)
- return null;
-
- CredentialsStorageService credentialsStorage
- = ServiceUtils.getService(
- bundleContext,
- CredentialsStorageService.class);
-
- return credentialsStorage.loadPassword(accountPrefix);
- }
-
- /**
- * 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
- */
- public AccountID loadAccount(Map<String, String> accountProperties)
- {
- AccountID accountID = createAccount(accountProperties);
-
- loadAccount(accountID);
-
- return accountID;
- }
-
- /**
- * Creates a protocol provider for the given <tt>accountID</tt> and
- * registers it in the bundle context. This method has a persistent
- * effect. Once created the resulting account will remain installed until
- * removed through the uninstallAccount method.
- *
- * @param accountID the account identifier
- * @return <tt>true</tt> if the account with the given <tt>accountID</tt> is
- * successfully loaded, otherwise returns <tt>false</tt>
- */
- public boolean loadAccount(AccountID accountID)
- {
- // Need to obtain the original user id property, instead of calling
- // accountID.getUserID(), because this method could return a modified
- // version of the user id property.
- String userID
- = accountID.getAccountPropertyString(
- ProtocolProviderFactory.USER_ID);
-
- ProtocolProviderService service = createService(userID, accountID);
-
- Dictionary<String, String> properties = new Hashtable<String, String>();
- properties.put(PROTOCOL, protocolName);
- properties.put(USER_ID, userID);
-
- ServiceRegistration<ProtocolProviderService> serviceRegistration
- = bundleContext.registerService(
- ProtocolProviderService.class,
- service,
- properties);
-
- if (serviceRegistration == null)
- {
- return false;
- }
- else
- {
- synchronized (registeredAccounts)
- {
- registeredAccounts.put(accountID, serviceRegistration);
- }
- return true;
- }
- }
-
- /**
- * Unloads the account corresponding to the given <tt>accountID</tt>.
- * Unregisters the corresponding protocol provider, but keeps the account in
- * contrast to the uninstallAccount method.
- *
- * @param accountID the account identifier
- * @return true if an account with the specified ID existed and was unloaded
- * and false otherwise.
- */
- public boolean unloadAccount(AccountID accountID)
- {
- // Unregister the protocol provider.
- ServiceReference<ProtocolProviderService> serRef
- = getProviderForAccount(accountID);
-
- if (serRef == null)
- {
- return false;
- }
-
- BundleContext bundleContext = getBundleContext();
- ProtocolProviderService protocolProvider
- = bundleContext.getService(serRef);
-
- try
- {
- protocolProvider.unregister();
- }
- catch (OperationFailedException ex)
- {
- logger.error(
- "Failed to unregister protocol provider for account: "
- + accountID + " caused by: " + ex);
- }
-
- ServiceRegistration<ProtocolProviderService> registration;
-
- synchronized (registeredAccounts)
- {
- registration = registeredAccounts.remove(accountID);
- }
- if (registration == null)
- {
- return false;
- }
-
- // Kill the service.
- registration.unregister();
-
- return true;
- }
-
- /**
- * Initializes and creates an account corresponding to the specified
- * accountProperties.
- *
- * @param accountProperties a set of protocol (or implementation) specific
- * properties defining the new account.
- * @return the AccountID of the newly created account
- */
- public AccountID createAccount(Map<String, String> accountProperties)
- {
- BundleContext bundleContext = getBundleContext();
- if (bundleContext == null)
- throw new NullPointerException(
- "The specified BundleContext was null");
-
- if (accountProperties == null)
- throw new NullPointerException(
- "The specified property map was null");
-
- String userID = accountProperties.get(USER_ID);
- if (userID == null)
- throw new NullPointerException(
- "The account properties contained no user id.");
-
- String protocolName = getProtocolName();
- if (!accountProperties.containsKey(PROTOCOL))
- accountProperties.put(PROTOCOL, protocolName);
-
- return createAccountID(userID, accountProperties);
- }
-
- /**
- * 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<String, String> 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
- */
- public String getProtocolName()
- {
- return protocolName;
- }
-
- /**
- * 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
- * that are persistently stored inside the configuration service.
- *
- * @param accountID the AccountID of the account to remove.
- *
- * @return true if an account has been removed and false otherwise.
- */
- protected boolean removeStoredAccount(AccountID accountID)
- {
- return getAccountManager().removeStoredAccount(this, accountID);
- }
-
- /**
- * Returns the prefix for all persistently stored properties of the account
- * with the specified id.
- * @param bundleContext a currently valid bundle context.
- * @param accountID the AccountID of the account whose properties we're
- * looking for.
- * @param sourcePackageName a String containing the package name of the
- * concrete factory class that extends us.
- * @return a String indicating the ConfigurationService property name
- * prefix under which all account properties are stored or null if no
- * account corresponding to the specified id was found.
- */
- public static String findAccountPrefix(BundleContext bundleContext,
- AccountID accountID,
- String sourcePackageName)
- {
- ServiceReference<ConfigurationService> confReference
- = bundleContext.getServiceReference(ConfigurationService.class);
- ConfigurationService configurationService
- = bundleContext.getService(confReference);
-
- //first retrieve all accounts that we've registered
- List<String> storedAccounts =
- configurationService.getPropertyNamesByPrefix(sourcePackageName,
- true);
-
- //find an account with the corresponding id.
- for (String accountRootPropertyName : storedAccounts)
- {
- //unregister the account in the configuration service.
- //all the properties must have been registered in the following
- //hierarchy:
- //net.java.sip.communicator.impl.protocol.PROTO_NAME.ACC_ID.PROP_NAME
- String accountUID = configurationService.getString(
- accountRootPropertyName //node id
- + "." + ACCOUNT_UID); // propname
-
- if (accountID.getAccountUniqueID().equals(accountUID))
- {
- return accountRootPropertyName;
- }
- }
- return null;
- }
-
- /**
- * Returns the name of the package that we're currently running in (i.e.
- * the name of the package containing the proto factory that extends us).
- *
- * @return a String containing the package name of the concrete factory
- * class that extends us.
- */
- private String getFactoryImplPackageName()
- {
- String className = getClass().getName();
-
- return className.substring(0, className.lastIndexOf('.'));
- }
-
- /**
- * Prepares the factory for bundle shutdown.
- */
- public void stop()
- {
- if (logger.isTraceEnabled())
- logger.trace("Preparing to stop all protocol providers of" + this);
-
- synchronized (registeredAccounts)
- {
- for (ServiceRegistration<ProtocolProviderService> reg
- : registeredAccounts.values())
- {
- 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<ProtocolProviderService> registeredAccount)
- {
- ProtocolProviderService protocolProviderService
- = getBundleContext().getService(registeredAccount.getReference());
-
- protocolProviderService.shutdown();
- }
-
- /**
- * Get the <tt>AccountManager</tt> of the protocol.
- *
- * @return <tt>AccountManager</tt> of the protocol
- */
- private AccountManager getAccountManager()
- {
- BundleContext bundleContext = getBundleContext();
- ServiceReference<AccountManager> serviceReference
- = bundleContext.getServiceReference(AccountManager.class);
-
- return bundleContext.getService(serviceReference);
- }
-
-
- /**
- * Finds registered <tt>ProtocolProviderFactory</tt> for given
- * <tt>protocolName</tt>.
- * @param bundleContext the OSGI bundle context that will be used.
- * @param protocolName the protocol name.
- * @return Registered <tt>ProtocolProviderFactory</tt> for given protocol
- * name or <tt>null</tt> if no provider was found.
- */
- static public ProtocolProviderFactory getProtocolProviderFactory(
- BundleContext bundleContext,
- String protocolName)
- {
- Collection<ServiceReference<ProtocolProviderFactory>> serRefs;
- String osgiFilter
- = "(" + ProtocolProviderFactory.PROTOCOL + "=" + protocolName + ")";
-
- try
- {
- serRefs
- = bundleContext.getServiceReferences(
- ProtocolProviderFactory.class,
- osgiFilter);
- }
- catch (InvalidSyntaxException ex)
- {
- serRefs = null;
- logger.error(ex);
- }
- if ((serRefs == null) || serRefs.isEmpty())
- return null;
- else
- return bundleContext.getService(serRefs.iterator().next());
- }
-}
+package net.java.sip.communicator.service.protocol; + +import java.lang.reflect.*; +import java.util.*; + +import net.java.sip.communicator.service.credentialsstorage.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.service.configuration.*; +import org.osgi.framework.*; + +/** + * The ProtocolProviderFactory is what actually creates instances of a + * ProtocolProviderService implementation. A provider factory would register, + * persistently store, and remove when necessary, ProtocolProviders. The way + * things are in the SIP Communicator, a user account is represented (in a 1:1 + * relationship) by an AccountID and a ProtocolProvider. In other words - one + * would have as many protocol providers installed in a given moment as they + * would user account registered through the various services. + * + * @author Emil Ivov + * @author Lubomir Marinov + */ +public abstract class ProtocolProviderFactory +{ + /** + * The <tt>Logger</tt> used by the <tt>ProtocolProviderFactory</tt> class + * and its instances for logging output. + */ + private static final Logger logger + = Logger.getLogger(ProtocolProviderFactory.class); + + /** + * Then name of a property which represents a password. + */ + public static final String PASSWORD = "PASSWORD"; + + /** + * The name of a property representing the name of the protocol for an + * ProtocolProviderFactory. + */ + public static final String PROTOCOL = "PROTOCOL_NAME"; + + /** + * The name of a property representing the path to protocol icons. + */ + public static final String PROTOCOL_ICON_PATH = "PROTOCOL_ICON_PATH"; + + /** + * The name of a property representing the path to the account icon to + * be used in the user interface, when the protocol provider service is not + * available. + */ + public static final String ACCOUNT_ICON_PATH = "ACCOUNT_ICON_PATH"; + + /** + * The name of a property which represents the AccountID of a + * ProtocolProvider and that, together with a password is used to login + * on the protocol network.. + */ + public static final String USER_ID = "USER_ID"; + + /** + * The name that should be displayed to others when we are calling or + * writing them. + */ + public static final String DISPLAY_NAME = "DISPLAY_NAME"; + + /** + * The name that should be displayed to the user on call via and chat via + * lists. + */ + public static final String ACCOUNT_DISPLAY_NAME = "ACCOUNT_DISPLAY_NAME"; + + /** + * The name of the property under which we store protocol AccountID-s. + */ + public static final String ACCOUNT_UID = "ACCOUNT_UID"; + + /** + * The name of the property under which we store protocol the address of + * a protocol centric entity (any protocol server). + */ + public static final String SERVER_ADDRESS = "SERVER_ADDRESS"; + + /** + * The name of the property under which we store the number of the port + * where the server stored against the SERVER_ADDRESS property is expecting + * connections to be made via this protocol. + */ + public static final String SERVER_PORT = "SERVER_PORT"; + + /** + * The name of the property under which we store the name of the transport + * protocol that needs to be used to access the server. + */ + public static final String SERVER_TRANSPORT = "SERVER_TRANSPORT"; + + /** + * The name of the property under which we store protocol the address of + * a protocol proxy. + */ + public static final String PROXY_ADDRESS = "PROXY_ADDRESS"; + + /** + * The name of the property under which we store the number of the port + * where the proxy stored against the PROXY_ADDRESS property is expecting + * connections to be made via this protocol. + */ + public static final String PROXY_PORT = "PROXY_PORT"; + + /** + * The name of the property which defines whether proxy is auto configured + * by the protocol by using known methods such as specific DNS queries. + */ + public static final String PROXY_AUTO_CONFIG = "PROXY_AUTO_CONFIG"; + + /** + * The property indicating the preferred UDP and TCP + * port to bind to for clear communications. + */ + public static final String PREFERRED_CLEAR_PORT_PROPERTY_NAME + = "net.java.sip.communicator.SIP_PREFERRED_CLEAR_PORT"; + + /** + * The property indicating the preferred TLS (TCP) + * port to bind to for secure communications. + */ + public static final String PREFERRED_SECURE_PORT_PROPERTY_NAME + = "net.java.sip.communicator.SIP_PREFERRED_SECURE_PORT"; + + /** + * The name of the property under which we store the the type of the proxy + * stored against the PROXY_ADDRESS property. Exact type values depend on + * protocols and among them are socks4, socks5, http and possibly others. + */ + public static final String PROXY_TYPE = "PROXY_TYPE"; + + /** + * The name of the property under which we store the the username for the + * proxy stored against the PROXY_ADDRESS property. + */ + public static final String PROXY_USERNAME = "PROXY_USERNAME"; + + /** + * The name of the property under which we store the the authorization name + * for the proxy stored against the PROXY_ADDRESS property. + */ + public static final String AUTHORIZATION_NAME = "AUTHORIZATION_NAME"; + + /** + * The name of the property under which we store the password for the proxy + * stored against the PROXY_ADDRESS property. + */ + public static final String PROXY_PASSWORD = "PROXY_PASSWORD"; + + /** + * The name of the property under which we store the name of the transport + * protocol that needs to be used to access the proxy. + */ + public static final String PROXY_TRANSPORT = "PROXY_TRANSPORT"; + + /** + * The name of the property that indicates whether loose routing should be + * forced for all traffic in an account, rather than routing through an + * outbound proxy which is the default for Jitsi. + */ + public static final String FORCE_PROXY_BYPASS = "FORCE_PROXY_BYPASS"; + + /** + * The name of the property that indicates whether the client must + * be registered with a registrar when making outgoing calls. + */ + public static final String MUST_REGISTER_TO_CALL = "MUST_REGISTER_TO_CALL"; + + /** + * The name of the property under which we store the user preference for a + * transport protocol to use (i.e. tcp or udp). + */ + public static final String PREFERRED_TRANSPORT = "PREFERRED_TRANSPORT"; + + /** + * The name of the property under which we store whether we generate + * resource values or we just use the stored one. + */ + public static final String AUTO_GENERATE_RESOURCE = "AUTO_GENERATE_RESOURCE"; + + /** + * The name of the property under which we store resources such as the + * jabber resource property. + */ + public static final String RESOURCE = "RESOURCE"; + + /** + * The name of the property under which we store resource priority. + */ + public static final String RESOURCE_PRIORITY = "RESOURCE_PRIORITY"; + + /** + * The name of the property which defines that the call is encrypted by + * default + */ + public static final String DEFAULT_ENCRYPTION = "DEFAULT_ENCRYPTION"; + + /** + * The name of the property that indicates the encryption protocols for this + * account. + */ + public static final String ENCRYPTION_PROTOCOL = "ENCRYPTION_PROTOCOL"; + + /** + * The name of the property that indicates the status (enabed or disabled) + * encryption protocols for this account. + */ + public static final String ENCRYPTION_PROTOCOL_STATUS + = "ENCRYPTION_PROTOCOL_STATUS"; + + /** + * The name of the property which defines if to include the ZRTP attribute + * to SIP/SDP + */ + public static final String DEFAULT_SIPZRTP_ATTRIBUTE = + "DEFAULT_SIPZRTP_ATTRIBUTE"; + + /** + * The name of the property which defines the ID of the client TLS + * certificate configuration entry. + */ + public static final String CLIENT_TLS_CERTIFICATE = + "CLIENT_TLS_CERTIFICATE"; + + /** + * The name of the property under which we store the boolean value + * indicating if the user name should be automatically changed if the + * specified name already exists. This property is meant to be used by IRC + * implementations. + */ + public static final String AUTO_CHANGE_USER_NAME = "AUTO_CHANGE_USER_NAME"; + + /** + * The name of the property under which we store the boolean value + * indicating if a password is required. Initially this property is meant to + * be used by IRC implementations. + */ + public static final String NO_PASSWORD_REQUIRED = "NO_PASSWORD_REQUIRED"; + + /** + * The name of the property under which we store if the presence is enabled. + */ + public static final String IS_PRESENCE_ENABLED = "IS_PRESENCE_ENABLED"; + + /** + * The name of the property under which we store if the p2p mode for SIMPLE + * should be forced. + */ + public static final String FORCE_P2P_MODE = "FORCE_P2P_MODE"; + + /** + * The name of the property under which we store the offline contact polling + * period for SIMPLE. + */ + public static final String POLLING_PERIOD = "POLLING_PERIOD"; + + /** + * The name of the property under which we store the chosen default + * subscription expiration value for SIMPLE. + */ + public static final String SUBSCRIPTION_EXPIRATION + = "SUBSCRIPTION_EXPIRATION"; + + /** + * Indicates if the server address has been validated. + */ + public static final String SERVER_ADDRESS_VALIDATED + = "SERVER_ADDRESS_VALIDATED"; + + /** + * Indicates if the server settings are over + */ + public static final String IS_SERVER_OVERRIDDEN + = "IS_SERVER_OVERRIDDEN"; + /** + * Indicates if the proxy address has been validated. + */ + public static final String PROXY_ADDRESS_VALIDATED + = "PROXY_ADDRESS_VALIDATED"; + + /** + * Indicates the search strategy chosen for the DICT protocole. + */ + public static final String STRATEGY = "STRATEGY"; + + /** + * Indicates a protocol that would not be shown in the user interface as an + * account. + */ + public static final String IS_PROTOCOL_HIDDEN = "IS_PROTOCOL_HIDDEN"; + + /** + * Indicates if the given account is the preferred account. + */ + public static final String IS_PREFERRED_PROTOCOL = "IS_PREFERRED_PROTOCOL"; + + /** + * The name of the property that would indicate if a given account is + * currently enabled or disabled. + */ + public static final String IS_ACCOUNT_DISABLED = "IS_ACCOUNT_DISABLED"; + + /** + * The name of the property that would indicate if a given account + * configuration form is currently hidden. + */ + public static final String IS_ACCOUNT_CONFIG_HIDDEN = "IS_CONFIG_HIDDEN"; + + /** + * The name of the property that would indicate if a given account + * status menu is currently hidden. + */ + public static final String IS_ACCOUNT_STATUS_MENU_HIDDEN = + "IS_STATUS_MENU_HIDDEN"; + + /** + * The name of the property that would indicate if a given account + * configuration is read only. + */ + public static final String IS_ACCOUNT_READ_ONLY = "IS_READ_ONLY"; + + /** + * The name of the property that would indicate if a given account + * groups are readonly, values can be all or a comma separated + * group names including root. + */ + public static final String ACCOUNT_READ_ONLY_GROUPS = "READ_ONLY_GROUPS"; + + /** + * Indicates if ICE should be used. + */ + public static final String IS_USE_ICE = "ICE_ENABLED"; + + /** + * Indicates if STUN server should be automatically discovered. + */ + public static final String AUTO_DISCOVER_STUN = "AUTO_DISCOVER_STUN"; + + /** + * Indicates if default STUN server would be used if no other STUN/TURN + * server are available. + */ + public static final String USE_DEFAULT_STUN_SERVER + = "USE_DEFAULT_STUN_SERVER"; + + /** + * The name of the boolean account property which indicates whether Jitsi + * Videobridge is to be used, if available and supported, for conference + * calls. + */ + public static final String USE_JITSI_VIDEO_BRIDGE + = "USE_JITSI_VIDEO_BRIDGE"; + + /** + * The name of the boolean account property which indicates whether Jitsi + * will use translator for media, instead of mixing, for conference + * calls. + * By default if supported mixing is used (audio mixed, video relayed). + */ + public static final String USE_TRANSLATOR_IN_CONFERENCE + = "USE_TRANSLATOR_IN_CONFERENCE"; + + /** + * The property name prefix for all stun server properties. We generally use + * this prefix in conjunction with an index which is how we store multiple + * servers. + */ + public static final String STUN_PREFIX = "STUN"; + + /** + * The base property name for address of additional STUN servers specified. + */ + public static final String STUN_ADDRESS = "ADDRESS"; + + /** + * The base property name for port of additional STUN servers specified. + */ + public static final String STUN_PORT = "PORT"; + + /** + * The base property name for username of additional STUN servers specified. + */ + public static final String STUN_USERNAME = "USERNAME"; + + /** + * The base property name for password of additional STUN servers specified. + */ + public static final String STUN_PASSWORD = "PASSWORD"; + + /** + * The base property name for the turn supported property of additional + * STUN servers specified. + */ + public static final String STUN_IS_TURN_SUPPORTED = "IS_TURN_SUPPORTED"; + + /** + * Indicates if JingleNodes should be used with ICE. + */ + public static final String IS_USE_JINGLE_NODES = "JINGLE_NODES_ENABLED"; + + /** + * Indicates if JingleNodes should be used with ICE. + */ + public static final String AUTO_DISCOVER_JINGLE_NODES + = "AUTO_DISCOVER_JINGLE_NODES"; + + /** + * Indicates if JingleNodes should use buddies to search for nodes. + */ + public static final String JINGLE_NODES_SEARCH_BUDDIES + = "JINGLE_NODES_SEARCH_BUDDIES"; + + /** + * Indicates if UPnP should be used with ICE. + */ + public static final String IS_USE_UPNP = "UPNP_ENABLED"; + + /** + * Indicates if we allow non-TLS connection. + */ + public static final String IS_ALLOW_NON_SECURE = "ALLOW_NON_SECURE"; + + /** + * Enable notifications for new voicemail messages. + */ + public static final String VOICEMAIL_ENABLED = "VOICEMAIL_ENABLED"; + + /** + * Address used to reach voicemail box, by services able to + * subscribe for voicemail new messages notifications. + */ + public static final String VOICEMAIL_URI = "VOICEMAIL_URI"; + + /** + * Address used to call to hear your messages stored on the server + * for your voicemail. + */ + public static final String VOICEMAIL_CHECK_URI = "VOICEMAIL_CHECK_URI"; + + /** + * Indicates if calling is disabled for a certain account. + */ + public static final String IS_CALLING_DISABLED_FOR_ACCOUNT + = "CALLING_DISABLED"; + + /** + * Indicates if desktop streaming/sharing is disabled for a certain account. + */ + public static final String IS_DESKTOP_STREAMING_DISABLED + = "DESKTOP_STREAMING_DISABLED"; + + /** + * Indicates if desktop remote control is disabled for a certain account. + */ + public static final String IS_DESKTOP_REMOTE_CONTROL_DISABLED + = "DESKTOP_REMOTE_CONTROL_DISABLED"; + + /** + * The sms default server address. + */ + public static final String SMS_SERVER_ADDRESS = "SMS_SERVER_ADDRESS"; + + /** + * Keep-alive method used by the protocol. + */ + public static final String KEEP_ALIVE_METHOD = "KEEP_ALIVE_METHOD"; + + /** + * The interval for keep-alives if any. + */ + public static final String KEEP_ALIVE_INTERVAL = "KEEP_ALIVE_INTERVAL"; + + /** + * The name of the property holding DTMF method. + */ + public static final String DTMF_METHOD = "DTMF_METHOD"; + + /** + * The minimal DTMF tone duration. + */ + public static final String DTMF_MINIMAL_TONE_DURATION + = "DTMF_MINIMAL_TONE_DURATION"; + + /** + * Paranoia mode when turned on requires all calls to be secure and + * indicated as such. + */ + public static final String MODE_PARANOIA = "MODE_PARANOIA"; + + /** + * The name of the "override encodings" property + */ + public static final String OVERRIDE_ENCODINGS = "OVERRIDE_ENCODINGS"; + + /** + * The prefix used to store account encoding properties + */ + public static final String ENCODING_PROP_PREFIX = "Encodings"; + + /** + * An account property to provide a connected account to check for + * its status. Used when the current provider need to reject calls + * but is missing presence operation set and need to check other + * provider for status. + */ + public static final String CUSAX_PROVIDER_ACCOUNT_PROP + = "cusax.XMPP_ACCOUNT_ID"; + + /** + * 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 Map<AccountID, ServiceRegistration<ProtocolProviderService>> + registeredAccounts + = new HashMap<AccountID, ServiceRegistration<ProtocolProviderService>>(); + + /** + * The name of the property that indicates the AVP type. + * <ul> + * <li>{@link #SAVP_OFF}</li> + * <li>{@link #SAVP_MANDATORY}</li> + * <li>{@link #SAVP_OPTIONAL}</li> + * </ul> + */ + public static final String SAVP_OPTION = "SAVP_OPTION"; + + /** + * Always use RTP/AVP + */ + public static final int SAVP_OFF = 0; + + /** + * Always use RTP/SAVP + */ + public static final int SAVP_MANDATORY = 1; + + /** + * Sends two media description, with RTP/SAVP being first. + */ + public static final int SAVP_OPTIONAL = 2; + + /** + * The name of the property that defines the enabled SDES cipher suites. + * Enabled suites are listed as CSV by their RFC name. + */ + public static final String SDES_CIPHER_SUITES = "SDES_CIPHER_SUITES"; + + /** + * The name of the property that defines the enabled/disabled state of + * message carbons. + */ + public static final String IS_CARBON_DISABLED = "CARBON_DISABLED"; + + /** + * Creates a new <tt>ProtocolProviderFactory</tt>. + * + * @param bundleContext the bundle context reference of the service + * @param protocolName the name of the protocol + */ + 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 + * registration is persistent and accounts that are registered during + * a particular sip-communicator session would be automatically reloaded + * during all following sessions until they are removed through the + * removeAccount method. + * + * @param userID 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 java.lang.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 java.lang.IllegalStateException if the account has already been + * installed. + * @throws java.lang.NullPointerException if any of the arguments is null. + */ + public abstract AccountID installAccount(String userID, + Map<String, String> accountProperties) + throws IllegalArgumentException, + IllegalStateException, + NullPointerException; + + + /** + * 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 abstract void modifyAccount( + ProtocolProviderService protocolProvider, + Map<String, String> accountProperties) + throws NullPointerException; + + /** + * Returns a copy of the list containing the <tt>AccountID</tt>s of all + * accounts currently registered in this protocol provider. + * @return a copy of the list containing the <tt>AccountID</tt>s of all + * accounts currently registered in this protocol provider. + */ + public ArrayList<AccountID> getRegisteredAccounts() + { + synchronized (registeredAccounts) + { + return new ArrayList<AccountID>(registeredAccounts.keySet()); + } + } + + /** + * Returns the ServiceReference for the protocol provider corresponding to + * the specified accountID or null if the accountID is unknown. + * @param accountID the accountID of the protocol provider we'd like to get + * @return a ServiceReference object to the protocol provider with the + * specified account id and null if the account id is unknown to the + * provider factory. + */ + public ServiceReference<ProtocolProviderService> getProviderForAccount( + AccountID accountID) + { + ServiceRegistration<ProtocolProviderService> registration; + + synchronized (registeredAccounts) + { + registration = registeredAccounts.get(accountID); + } + + try + { + if (registration != null) + return registration.getReference(); + } + catch (IllegalStateException ise) + { + synchronized (registeredAccounts) + { + registeredAccounts.remove(accountID); + } + } + + return null; + } + + /** + * Removes the specified account from the list of accounts that this + * provider factory is handling. If the specified accountID is unknown to + * the ProtocolProviderFactory, the call has no effect and false is + * returned. This method is persistent in nature and once called the account + * corresponding to the specified ID will not be loaded during future runs + * of the project. + * + * @param accountID the ID of the account to remove. + * @return true if an account with the specified ID existed and was removed + * and false otherwise. + */ + public boolean uninstallAccount(AccountID accountID) + { + // Unregister the protocol provider. + ServiceReference<ProtocolProviderService> serRef + = getProviderForAccount(accountID); + + boolean wasAccountExisting = false; + + // If the protocol provider service is registered, first unregister the + // service. + if (serRef != null) + { + BundleContext bundleContext = getBundleContext(); + ProtocolProviderService protocolProvider + = bundleContext.getService(serRef); + + try + { + protocolProvider.unregister(); + } + catch (OperationFailedException ex) + { + logger.error( + "Failed to unregister protocol provider for account: " + + accountID + " caused by: " + ex); + } + } + + ServiceRegistration<ProtocolProviderService> registration; + + synchronized (registeredAccounts) + { + registration = registeredAccounts.remove(accountID); + } + + // first remove the stored account so when PP is unregistered we can + // distinguish between deleted or just disabled account + wasAccountExisting = removeStoredAccount(accountID); + + if (registration != null) + { + // Kill the service. + registration.unregister(); + } + + return wasAccountExisting; + } + + /** + * 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) + { + this.storeAccount(accountID, true); + } + + /** + * 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. + * @param isModification if <tt>false</tt> there must be no such already + * loaded account, it <tt>true</tt> ist modification of an existing account. + * Usually we use this method with <tt>false</tt> in method installAccount + * and with <tt>true</tt> or the overridden method in method + * modifyAccount. + */ + protected void storeAccount(AccountID accountID, boolean isModification) + { + if(!isModification + && getAccountManager().getStoredAccounts().contains(accountID)) + { + throw new IllegalStateException( + "An account for id " + accountID.getUserID() + + " was already loaded!"); + } + + try + { + getAccountManager().storeAccount(this, accountID); + } + catch (OperationFailedException ofex) + { + throw new UndeclaredThrowableException(ofex); + } + } + + /** + * 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 + { + try + { + storePassword(getBundleContext(), accountID, password); + } + catch (OperationFailedException ofex) + { + throw new UndeclaredThrowableException(ofex); + } + } + + /** + * Saves the password for the specified account after scrambling it a bit + * 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 <tt>AccountID</tt> of the account whose password is + * to be stored + * @param password the password to be stored + * + * @throws IllegalArgumentException if no account corresponding to + * <tt>accountID</tt> has been previously stored. + * @throws OperationFailedException if anything goes wrong while storing the + * specified <tt>password</tt> + */ + protected void storePassword(BundleContext bundleContext, + AccountID accountID, + String password) + throws IllegalArgumentException, + OperationFailedException + { + String accountPrefix + = findAccountPrefix( + bundleContext, + accountID, + getFactoryImplPackageName()); + + if (accountPrefix == null) + { + throw + new IllegalArgumentException( + "No previous records found for account ID: " + + accountID.getAccountUniqueID() + + " in package" + + getFactoryImplPackageName()); + } + + CredentialsStorageService credentialsStorage + = ServiceUtils.getService( + bundleContext, + CredentialsStorageService.class); + + if (!credentialsStorage.storePassword(accountPrefix, password)) + { + throw + new OperationFailedException( + "CredentialsStorageService failed to storePassword", + OperationFailedException.GENERAL_ERROR); + } + + // Update password property also in the AccountID + // to prevent it from being removed during account reload + // in some cases. + accountID.setPassword(password); + + } + + /** + * 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.. + * + * @return a String containing the password for the specified accountID. + */ + protected String loadPassword(BundleContext bundleContext, + AccountID accountID) + { + String accountPrefix = findAccountPrefix( + bundleContext, accountID, getFactoryImplPackageName()); + + if (accountPrefix == null) + return null; + + CredentialsStorageService credentialsStorage + = ServiceUtils.getService( + bundleContext, + CredentialsStorageService.class); + + return credentialsStorage.loadPassword(accountPrefix); + } + + /** + * 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 + */ + public AccountID loadAccount(Map<String, String> accountProperties) + { + AccountID accountID = createAccount(accountProperties); + + loadAccount(accountID); + + return accountID; + } + + /** + * Creates a protocol provider for the given <tt>accountID</tt> and + * registers it in the bundle context. This method has a persistent + * effect. Once created the resulting account will remain installed until + * removed through the uninstallAccount method. + * + * @param accountID the account identifier + * @return <tt>true</tt> if the account with the given <tt>accountID</tt> is + * successfully loaded, otherwise returns <tt>false</tt> + */ + public boolean loadAccount(AccountID accountID) + { + // Need to obtain the original user id property, instead of calling + // accountID.getUserID(), because this method could return a modified + // version of the user id property. + String userID + = accountID.getAccountPropertyString( + ProtocolProviderFactory.USER_ID); + + ProtocolProviderService service = createService(userID, accountID); + + Dictionary<String, String> properties = new Hashtable<String, String>(); + properties.put(PROTOCOL, protocolName); + properties.put(USER_ID, userID); + + ServiceRegistration<ProtocolProviderService> serviceRegistration + = bundleContext.registerService( + ProtocolProviderService.class, + service, + properties); + + if (serviceRegistration == null) + { + return false; + } + else + { + synchronized (registeredAccounts) + { + registeredAccounts.put(accountID, serviceRegistration); + } + return true; + } + } + + /** + * Unloads the account corresponding to the given <tt>accountID</tt>. + * Unregisters the corresponding protocol provider, but keeps the account in + * contrast to the uninstallAccount method. + * + * @param accountID the account identifier + * @return true if an account with the specified ID existed and was unloaded + * and false otherwise. + */ + public boolean unloadAccount(AccountID accountID) + { + // Unregister the protocol provider. + ServiceReference<ProtocolProviderService> serRef + = getProviderForAccount(accountID); + + if (serRef == null) + { + return false; + } + + BundleContext bundleContext = getBundleContext(); + ProtocolProviderService protocolProvider + = bundleContext.getService(serRef); + + try + { + protocolProvider.unregister(); + } + catch (OperationFailedException ex) + { + logger.error( + "Failed to unregister protocol provider for account: " + + accountID + " caused by: " + ex); + } + + ServiceRegistration<ProtocolProviderService> registration; + + synchronized (registeredAccounts) + { + registration = registeredAccounts.remove(accountID); + } + if (registration == null) + { + return false; + } + + // Kill the service. + registration.unregister(); + + return true; + } + + /** + * Initializes and creates an account corresponding to the specified + * accountProperties. + * + * @param accountProperties a set of protocol (or implementation) specific + * properties defining the new account. + * @return the AccountID of the newly created account + */ + public AccountID createAccount(Map<String, String> accountProperties) + { + BundleContext bundleContext = getBundleContext(); + if (bundleContext == null) + throw new NullPointerException( + "The specified BundleContext was null"); + + if (accountProperties == null) + throw new NullPointerException( + "The specified property map was null"); + + String userID = accountProperties.get(USER_ID); + if (userID == null) + throw new NullPointerException( + "The account properties contained no user id."); + + String protocolName = getProtocolName(); + if (!accountProperties.containsKey(PROTOCOL)) + accountProperties.put(PROTOCOL, protocolName); + + return createAccountID(userID, accountProperties); + } + + /** + * 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<String, String> 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 + */ + public String getProtocolName() + { + return protocolName; + } + + /** + * 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 + * that are persistently stored inside the configuration service. + * + * @param accountID the AccountID of the account to remove. + * + * @return true if an account has been removed and false otherwise. + */ + protected boolean removeStoredAccount(AccountID accountID) + { + return getAccountManager().removeStoredAccount(this, accountID); + } + + /** + * Returns the prefix for all persistently stored properties of the account + * with the specified id. + * @param bundleContext a currently valid bundle context. + * @param accountID the AccountID of the account whose properties we're + * looking for. + * @param sourcePackageName a String containing the package name of the + * concrete factory class that extends us. + * @return a String indicating the ConfigurationService property name + * prefix under which all account properties are stored or null if no + * account corresponding to the specified id was found. + */ + public static String findAccountPrefix(BundleContext bundleContext, + AccountID accountID, + String sourcePackageName) + { + ServiceReference<ConfigurationService> confReference + = bundleContext.getServiceReference(ConfigurationService.class); + ConfigurationService configurationService + = bundleContext.getService(confReference); + + //first retrieve all accounts that we've registered + List<String> storedAccounts = + configurationService.getPropertyNamesByPrefix(sourcePackageName, + true); + + //find an account with the corresponding id. + for (String accountRootPropertyName : storedAccounts) + { + //unregister the account in the configuration service. + //all the properties must have been registered in the following + //hierarchy: + //net.java.sip.communicator.impl.protocol.PROTO_NAME.ACC_ID.PROP_NAME + String accountUID = configurationService.getString( + accountRootPropertyName //node id + + "." + ACCOUNT_UID); // propname + + if (accountID.getAccountUniqueID().equals(accountUID)) + { + return accountRootPropertyName; + } + } + return null; + } + + /** + * Returns the name of the package that we're currently running in (i.e. + * the name of the package containing the proto factory that extends us). + * + * @return a String containing the package name of the concrete factory + * class that extends us. + */ + private String getFactoryImplPackageName() + { + String className = getClass().getName(); + + return className.substring(0, className.lastIndexOf('.')); + } + + /** + * Prepares the factory for bundle shutdown. + */ + public void stop() + { + if (logger.isTraceEnabled()) + logger.trace("Preparing to stop all protocol providers of" + this); + + synchronized (registeredAccounts) + { + for (ServiceRegistration<ProtocolProviderService> reg + : registeredAccounts.values()) + { + 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<ProtocolProviderService> registeredAccount) + { + ProtocolProviderService protocolProviderService + = getBundleContext().getService(registeredAccount.getReference()); + + protocolProviderService.shutdown(); + } + + /** + * Get the <tt>AccountManager</tt> of the protocol. + * + * @return <tt>AccountManager</tt> of the protocol + */ + private AccountManager getAccountManager() + { + BundleContext bundleContext = getBundleContext(); + ServiceReference<AccountManager> serviceReference + = bundleContext.getServiceReference(AccountManager.class); + + return bundleContext.getService(serviceReference); + } + + + /** + * Finds registered <tt>ProtocolProviderFactory</tt> for given + * <tt>protocolName</tt>. + * @param bundleContext the OSGI bundle context that will be used. + * @param protocolName the protocol name. + * @return Registered <tt>ProtocolProviderFactory</tt> for given protocol + * name or <tt>null</tt> if no provider was found. + */ + static public ProtocolProviderFactory getProtocolProviderFactory( + BundleContext bundleContext, + String protocolName) + { + Collection<ServiceReference<ProtocolProviderFactory>> serRefs; + String osgiFilter + = "(" + ProtocolProviderFactory.PROTOCOL + "=" + protocolName + ")"; + + try + { + serRefs + = bundleContext.getServiceReferences( + ProtocolProviderFactory.class, + osgiFilter); + } + catch (InvalidSyntaxException ex) + { + serRefs = null; + logger.error(ex); + } + if ((serRefs == null) || serRefs.isEmpty()) + return null; + else + return bundleContext.getService(serRefs.iterator().next()); + } +} |