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

Reply via email to