SLING-6031 Teleporter.getService() should wait for required services

git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1759492 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/sling/junit/rules/ServerSideTeleporter.java b/src/main/java/org/apache/sling/junit/rules/ServerSideTeleporter.java
index 2d17f6f..055cbc3 100644
--- a/src/main/java/org/apache/sling/junit/rules/ServerSideTeleporter.java
+++ b/src/main/java/org/apache/sling/junit/rules/ServerSideTeleporter.java
@@ -31,6 +31,8 @@
     private final List<ServiceReference> toUnget = new ArrayList<ServiceReference>();
     private final BundleContext bundleContext;
     
+    private static final int WAITFOR_SERVICE_TIMEOUT_DEFAULT_SECONDS = 10;
+    
     ServerSideTeleporter() {
         bundleContext = Activator.getBundleContext();
         if(bundleContext == null) {
@@ -48,9 +50,41 @@
         }
     }
 
+    /**
+     * Get OSGi service - if it is not available (yet?) try again and again until the configured timeout is reached.
+     */
     public <T> T getService (Class<T> serviceClass, String ldapFilter) {
+        String configuredTimeout = (String)bundleContext.getBundle().getHeaders().get("Sling-Test-WaitForService-Timeout");
+        if (configuredTimeout == null) {
+            configuredTimeout = Integer.toString(WAITFOR_SERVICE_TIMEOUT_DEFAULT_SECONDS);
+        }
+        final long timeout = System.currentTimeMillis() + Integer.parseInt(configuredTimeout) * 1000;
+        
+        while (System.currentTimeMillis() < timeout) {
+            try {
+                T service = getServiceInternal(serviceClass, ldapFilter);
+                if (service != null) {
+                    return service;
+                }
+            }
+            catch (IllegalStateException ex) {
+                // ignore, try again
+            }
+            try {
+                Thread.sleep(50L);
+            }
+            catch (InterruptedException ex) {
+                // ignore
+            }
+        }
+        throw new IllegalStateException(
+                "unable to get a service reference, class=" + serviceClass.getName() + ", filter='" + ldapFilter + "'");
+    }
+
+    private <T> T getServiceInternal (Class<T> serviceClass, String ldapFilter) {
         final ServiceGetter sg = new ServiceGetter(bundleContext, serviceClass, ldapFilter);
         toUnget.add(sg.serviceReference);
         return serviceClass.cast(sg.service);
     }
+
 }