Dependency Manager - Resource Dependency

A resource dependency allows you to depend on a resource. A resource is a URL and you can use a filter condition based on protocol, host, port, path and URL.

To define a resource dependency, you need to use the ResourceDependecy interface. This interface can be created using DependencyActivatorBase.createResourceDependency() or DependencyManager.createResourceDependency() methods;

Here is an example where a bundle activation declares a VideoPlayer component which depends on a resource URL. The component uses an optional dependency callback, which is invoked each time an URL is registered.

public class Activator extends DependencyActivatorBase {
    @Override
    public void init(BundleContext ctx, DependencyManager dm) throws Exception {
        Component videoPlayer = createComponent()
        		.setImplementation(VideoPlayer.class)
        		.add(createResourceDependency().setFilter("(&(path=/path/to/*.txt)(host=localhost))").setCallbacks("play", null));
        dm.add(videoPlayer);
    }
}

public class VideoPlayer {
	void play(URL url) {
		System.out.println("play: " + url);

	}
}

And here is a component which registers some URL resources:

public class Activator extends DependencyActivatorBase {
    @Override
    public void init(BundleContext ctx, DependencyManager dm) throws Exception {
    	// add resource provider
        URL[] resourceURLs = new URL[] {
        		new URL("file://localhost/path/to/file1.txt"),
        		new URL("file://localhost/path/to/file2.txt")
        };

        Component resourceProvider = createComponent()
        		.setImplementation(new ResourceProvider(ctx, resourceURLs))
        		.add(dm.createServiceDependency().setService(ResourceHandler.class).setCallbacks("add", "remove"));
        dm.add(resourceProvider);
    }
}

class ResourceProvider {
	final URL[] m_resources;
    final BundleContext m_context;
    final Map<ResourceHandler, Filter> m_handlers = new HashMap<>();

	ResourceProvider(BundleContext ctx, URL ... resources) {
		m_context = ctx;
		m_resources = resources;
	}

	public void add(ServiceReference<?> ref, ResourceHandler handler) {
        String filterString = (String) ref.getProperty("filter");
        Filter filter = null;
        if (filterString != null) {
            try {
                filter = m_context.createFilter(filterString);
            }
            catch (InvalidSyntaxException e) {
                return;
            }
        }
        for (int i = 0; i < m_resources.length; i++) {
            if (filter == null || filter.match((Dictionary<String, ?>) ResourceUtil.createProperties(m_resources[i]))) {
                synchronized (m_handlers) {
                    m_handlers.put(handler, filter);
                }
                handler.added(m_resources[i]);
            }
        }
    }

    public void remove(ServiceReference<?> ref, ResourceHandler handler) {
        Filter filter;
        synchronized (m_handlers) {
            filter = (Filter) m_handlers.remove(handler);
        }
        if (filter != null) {
            for (int i = 0; i < m_resources.length; i++) {
                if (filter == null || filter.match((Dictionary<String, ?>) ResourceUtil.createProperties(m_resources[i]))) {
                    handler.removed(m_resources[i]);
                }
            }
        }
    }