/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.java.sip.communicator.service.protocol;
import java.util.*;
import net.java.sip.communicator.service.protocol.event.*;
import org.osgi.framework.*;
/**
* Provides utilities to aid the manipulation of {@link AccountManager}.
*
* @author Lyubomir Marinov
*/
public final class AccountManagerUtils
{
private static AccountManager getAccountManager(BundleContext bundleContext)
{
return
bundleContext.getService(
bundleContext.getServiceReference(AccountManager.class));
}
/**
* Starts a specific <code>Bundle</code> and waits for the
* <code>AccountManager</code> available in a specific
* <code>BundleContext</code> to load the stored accounts of a
* <code>ProtocolProviderFactory</code> with a specific protocol name.
*
* @param bundleContextWithAccountManager
* the <code>BundleContext</code> in which an
* <code>AccountManager</code> service is registered
* @param bundleToStart
* the <code>Bundle</code> to be started
* @param protocolNameToWait
* the protocol name of a <code>ProtocolProviderFactory</code> to
* wait the end of the loading of the stored accounts for
* @throws BundleException
* @throws InterruptedException
* if any thread interrupted the current thread before or while
* the current thread was waiting for the loading of the stored
* accounts
*/
public static void startBundleAndWaitStoredAccountsLoaded(
BundleContext bundleContextWithAccountManager,
final Bundle bundleToStart,
final String protocolNameToWait)
throws BundleException,
InterruptedException
{
AccountManager accountManager
= getAccountManager(bundleContextWithAccountManager);
final boolean[] storedAccountsAreLoaded = new boolean[1];
AccountManagerListener listener = new AccountManagerListener()
{
public void handleAccountManagerEvent(AccountManagerEvent event)
{
if (AccountManagerEvent.STORED_ACCOUNTS_LOADED
!= event.getType())
return;
ProtocolProviderFactory factory = event.getFactory();
/*
* If the event is for a factory with a protocol name other than
* protocolNameToWait, it's not the one we're waiting for.
*/
if ((factory != null)
&& !protocolNameToWait
.equals(factory.getProtocolName()))
return;
/*
* If the event if for a factory which is no longer registered,
* then it's not the one we're waiting for because we're waiting
* for the specified bundle to start and register a factory.
*/
if (factory != null)
{
BundleContext bundleContext
= bundleToStart.getBundleContext();
/*
* If the specified bundle still hasn't started, the event
* cannot be the one we're waiting for.
*/
if (bundleContext == null)
return;
Collection<ServiceReference<ProtocolProviderFactory>> factoryRefs;
try
{
factoryRefs
= bundleContext.getServiceReferences(
ProtocolProviderFactory.class,
"("
+ ProtocolProviderFactory.PROTOCOL
+ "="
+ protocolNameToWait
+ ")");
}
catch (InvalidSyntaxException isex)
{
/*
* Not likely so ignore it and assume the event is for
* a valid factory.
*/
factoryRefs = null;
}
if ((factoryRefs != null) && !factoryRefs.isEmpty())
{
boolean factoryIsRegistered = false;
for (ServiceReference<ProtocolProviderFactory> factoryRef
: factoryRefs)
{
if (factory == bundleContext.getService(factoryRef))
{
factoryIsRegistered = true;
break;
}
}
if (!factoryIsRegistered)
return;
}
}
synchronized (storedAccountsAreLoaded)
{
storedAccountsAreLoaded[0] = true;
storedAccountsAreLoaded.notify();
}
}
};
accountManager.addListener(listener);
try
{
bundleToStart.start();
while (true)
{
synchronized (storedAccountsAreLoaded)
{
if (storedAccountsAreLoaded[0])
{
break;
}
storedAccountsAreLoaded.wait();
}
}
}
finally
{
accountManager.removeListener(listener);
}
}
/**
* Prevents the creation of <code>AccountManagerUtils</code> instances.
*/
private AccountManagerUtils()
{
}
}