diff --git a/src/net/java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java index 5aa1b0fbe..64c47dfea 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java @@ -7,6 +7,7 @@ import java.text.*; import java.util.*; +import java.util.concurrent.*; import net.java.sip.communicator.service.argdelegation.*; import net.java.sip.communicator.service.gui.*; @@ -76,6 +77,12 @@ public class UriHandlerSipImpl */ private List uris; + /** + * ExecutorService used to schedule a dialing attempt after a delay. + */ + private static final ScheduledExecutorService worker = + Executors.newSingleThreadScheduledExecutor(); + /** * Creates an instance of this uri handler, so that it would start handling * URIs by passing them to the providers registered by protoFactory @@ -254,8 +261,7 @@ public String getProtocol() } /** - * Parses the specified URI and creates a call with the currently active - * telephony operation set. + * Parses the specified URI and tries to create a call when online. * * @param uri the SIP URI that we have to call. */ @@ -301,6 +307,80 @@ public void handleUri(String uri) return; } + if(provider.getRegistrationState() == RegistrationState.REGISTERED) + { + handleUri(uri, provider); + } + else + { + // Allow a grace period for the provider to register in case + // we have just started up + DelayedHandler task = new DelayedHandler(uri, provider); + task.schedule(); + } + } + + /** + * This class is a Runnable for checking if the provider is ready + * (which may take a second or two after startup) rather + * than immediately failing the dialing attempt with an error. + */ + private class DelayedHandler + implements Runnable + { + final static int RETRIES = 8; + final static int RETRY_DELAY = 250; + + private String uri; + private ProtocolProviderService provider; + int retries = RETRIES; + + /** + * Initialize this Runnable, storing the values needed + * when the timeout occurs. + * + * @param uri the URI to try and dial + * @param provider the provider to use + */ + public DelayedHandler(String uri, ProtocolProviderService provider) + { + this.uri = uri; + this.provider = provider; + } + + /** + * Tells the Runnable to schedule itself + */ + public void schedule() + { + worker.schedule(this, RETRY_DELAY, TimeUnit.MILLISECONDS); + } + + /** + * Executed after the timeout elapses. + * + * Checks if the registration is complete or if we had enough retries + * and then tries to dial. + */ + public void run() { + if(retries-- == 0 || + provider.getRegistrationState() == RegistrationState.REGISTERED) + { + handleUri(uri, provider); + return; + } + // retry after another delay + schedule(); + } + } + + /** + * Creates a call with the currently active telephony operation set. + * + * @param uri the SIP URI that we have to call. + */ + protected void handleUri(String uri, ProtocolProviderService provider) + { //handle "sip://" URIs as "sip:" if(uri != null) uri = uri.replace("sip://", "sip:");