osgiaemservlet-filterssling

Create/modify and register filters in OSGI programmatically


Is it possible to register new filters at runtime in OSGI ?

Use case is the following. We use Adobe AEM CMS with multiple tenants. Now we have a filter that protects access to particular resources based on filter patterns. Here is the header of a filter class that intercepts requests to paths that contain the fragment "protected" for tenant1.

@Component(service = Filter.class,
    property = {
            EngineConstants.SLING_FILTER_SCOPE + "=" + EngineConstants.FILTER_SCOPE_REQUEST,
            EngineConstants.SLING_FILTER_PATTERN + "=" + "/content/dam/tenant1/.*/protected/.*"
    })
 public class ProtectedResourcesFilter implements Filter ....

Now, whenevever we get tenant2 we would like to extend the ProtectedResourcesFilter with another pattern. Is it possible to modify the EngineConstants.SLING_FILTER_PATTERN and reload the filter?

Or is it better to create and register a new filter at runtime in OSGI ?


Solution

  • You can register new OSGi services at runtime.

    To do so, you need to have a BundleContext object around. This may happen in a different component that you register with Declarative Services ( via @Component ) or in a Bundle Activator.

    A sample method is below

    private ServiceRegistration<Filter> registerService(BundleContext ctx, String tenantId) {
        Filter newService = createFilterInstance();
        Dictionary<String, ?> props = new Hashtable<>();
        props.put(EngineConstants.SLING_FILTER_SCOPE, EngineConstants.FILTER_SCOPE_REQUEST);
        props.put(EngineConstants.SLING_FILTER_PATTERN, "/content/dam/" + tenantId + "/.*/protected/.*");
        return ctx.registerService(Filter.class, newService, props);
    }
    

    The only catch here is that you need to manage the lifecycle of these services, so you are responsible for figuring out when to register a new service and also when to unregister it.