You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@sling.apache.org by Olaf Otto <ol...@unic.com> on 2015/06/09 09:52:20 UTC

SLING-2920 / programmatically adjusting the filter order via service.ranking

Hi all,

I am implementing a programmatic solution to modify the ranking of "legacy" filters with regard to the changed filter order in Sling Engine 2.3.3 (https://issues.apache.org/jira/browse/SLING-2920). I couldn't really figure out a "clean" way to alter the service properties of arbitrary (including on-managed) filter components programmatically, but I got it working with a bit of reflection. That said, here is my solution sketch (it works) - does anyone know of a cleaner way to adjust these properties at runtime?

@Component(immediate = true)
public class SlingEngineFilterOrderAdjuster {
    private static final String PROPERTY_RANKING_ADJUSTED = "aem61.ranking.adjusted";
    private final Logger logger = LoggerFactory.getLogger(getClass());
    private ServiceTracker tracker;

    @Activate
    @SuppressWarnings("unchecked")
    protected void activate(ComponentContext context) {
        Filter filter;
        try {
            filter = context.getBundleContext().createFilter(
                    "(&" +
                            "(objectClass=" + javax.servlet.Filter.class.getName() + ")&(" +
                            "|(component.name=my.package.namesppace.*)(" + BUNDLE_SYMBOLICNAME + "=my.bundle.namespace.*)))");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return;
        }

        tracker = new ServiceTracker(context.getBundleContext(), filter, null) {
            @Override
            public Object addingService(ServiceReference reference) {
                if (reference.getProperty(PROPERTY_RANKING_ADJUSTED) != null) {
                    return super.addingService(reference);
                }

                try {
                    Method getRegistration = reference.getClass().getDeclaredMethod("getRegistration", (Class[]) null);
                    getRegistration.setAccessible(true);
                    ServiceRegistration registration = (ServiceRegistration) getRegistration.invoke(reference);

                    Dictionary<String, Object> properties = new Hashtable<>();
                    for (String key : reference.getPropertyKeys()) {
                        if (SERVICE_RANKING.equals(key)) {
                            Integer value = (Integer) reference.getProperty(key);
                            properties.put(key, -1 * value);
                        } else {
                            properties.put(key, reference.getProperty(key));
                        }
                        properties.put(PROPERTY_RANKING_ADJUSTED, true);
                    }
                    registration.setProperties(properties);

                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                }

                return super.addingService(reference);
            }
        };

        tracker.open(true);
    }

    @Deactivate
    protected void deactivate() {
        tracker.close();
    }


Regards,
Olaf

Re: SLING-2920 / programmatically adjusting the filter order via service.ranking

Posted by Bertrand Delacretaz <bd...@apache.org>.
Hi Olaf,

On Tue, Jun 9, 2015 at 9:52 AM, Olaf Otto <ol...@unic.com> wrote:
> ...I am implementing a programmatic solution to modify the ranking of "legacy" filters
> with regards to the changed filter order...SLING-2920

Late reply to that one - I have played with David Bosschaert's Service
Jockey which allows for manipulating service properties using OSGi
hooks and that looks promising. Details at SLING-2920, and the
required code (just an XML config actually) is at
https://github.com/bdelacretaz/sling-filters-jockey-poc

-Bertrand