2 * Copyright (c) 2016 Brocade Communications Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.config.api.osgi;
10 import java.util.concurrent.TimeUnit;
11 import javax.annotation.Nonnull;
12 import org.osgi.framework.BundleContext;
13 import org.osgi.framework.Constants;
14 import org.osgi.framework.InvalidSyntaxException;
15 import org.osgi.util.tracker.ServiceTracker;
16 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
20 * Tracker that waits for an OSGi service.
22 * @author Thomas Pantelis
24 public final class WaitingServiceTracker<T> implements AutoCloseable {
25 private static final Logger LOG = LoggerFactory.getLogger(WaitingServiceTracker.class);
26 public static final long FIVE_MINUTES = TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES);
28 private final ServiceTracker<T, ?> tracker;
29 private final Class<T> serviceInterface;
31 private WaitingServiceTracker(Class<T> serviceInterface, ServiceTracker<T, ?> tracker) {
32 this.tracker = tracker;
33 this.serviceInterface = serviceInterface;
37 * Waits for an OSGi services.
39 * @param timeoutInMillis the timeout in millis
40 * @return the service instance
41 * @throws ServiceNotFoundException if it times out or is interrupted
43 @SuppressWarnings("unchecked")
44 public T waitForService(long timeoutInMillis) throws ServiceNotFoundException {
46 T service = (T) tracker.waitForService(timeoutInMillis);
48 throw new ServiceNotFoundException(String.format("OSGi Service %s was not found after %d ms",
49 serviceInterface, timeoutInMillis));
53 } catch(InterruptedException e) {
54 throw new ServiceNotFoundException(String.format("Wait for OSGi service %s was interrrupted",
60 * Creates an instance.
62 * @param serviceInterface the service interface
63 * @param context the BundleContext
64 * @return new WaitingServiceTracker instance
66 public static <T> WaitingServiceTracker<T> create(@Nonnull Class<T> serviceInterface, @Nonnull BundleContext context) {
67 ServiceTracker<T, ?> tracker = new ServiceTracker<>(context, serviceInterface, null);
69 return new WaitingServiceTracker<>(serviceInterface, tracker);
73 * Creates an instance.
75 * @param serviceInterface the service interface
76 * @param context the BundleContext
77 * @param filter the OSGi service filter
78 * @return new WaitingServiceTracker instance
80 public static <T> WaitingServiceTracker<T> create(@Nonnull Class<T> serviceInterface, @Nonnull BundleContext context,
81 @Nonnull String filter) {
82 String newFilter = String.format("(&(%s=%s)%s)", Constants.OBJECTCLASS, serviceInterface.getName(), filter);
84 ServiceTracker<T, ?> tracker = new ServiceTracker<>(context, context.createFilter(newFilter), null);
86 return new WaitingServiceTracker<>(serviceInterface, tracker);
87 } catch(InvalidSyntaxException e) {
88 throw new IllegalArgumentException(String.format("Invalid OSGi filter %s", newFilter), e);
96 } catch(RuntimeException e) {
97 // The ServiceTracker could throw IllegalStateException if the BundleContext is already closed.
98 // This is benign so ignore it.
99 LOG.debug("Error closing ServiceTracker", e);