Author: cziegeler
Date: Thu May 22 12:47:10 2014
New Revision: 1596846

URL: http://svn.apache.org/r1596846
Log:
SLING-2920 : Wrong handling of Sling Filter ordering. Apply patch from Felix 
Meschberger, add test case and remove synced method calls for request handling

Added:
    
sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/filter/
    
sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/filter/SlingFilterChainHelperTest.java
   (with props)
Modified:
    
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/WebConsoleConfigPrinter.java
    
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/filter/ServletFilterManager.java
    
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/filter/SlingFilterChainHelper.java

Modified: 
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/WebConsoleConfigPrinter.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/WebConsoleConfigPrinter.java?rev=1596846&r1=1596845&r2=1596846&view=diff
==============================================================================
--- 
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/WebConsoleConfigPrinter.java
 (original)
+++ 
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/WebConsoleConfigPrinter.java
 Thu May 22 12:47:10 2014
@@ -87,8 +87,10 @@ public class WebConsoleConfigPrinter {
                 pw.print(entry.getOrder());
                 pw.print(" : ");
                 pw.print(entry.getFilter().getClass());
-                pw.print(" (");
-                pw.print(entry.getFitlerId());
+                pw.print(" (id: ");
+                pw.print(entry.getFilterId());
+                pw.print(", property: ");
+                pw.print(entry.getOrderSource());
                 pw.println(")");
             }
         }

Modified: 
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/filter/ServletFilterManager.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/filter/ServletFilterManager.java?rev=1596846&r1=1596845&r2=1596846&view=diff
==============================================================================
--- 
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/filter/ServletFilterManager.java
 (original)
+++ 
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/filter/ServletFilterManager.java
 Thu May 22 12:47:10 2014
@@ -187,26 +187,29 @@ public class ServletFilterManager extend
                 filter.init(config);
 
                 // service id
-                Long serviceId = (Long) 
reference.getProperty(Constants.SERVICE_ID);
+                final Long serviceId = (Long) 
reference.getProperty(Constants.SERVICE_ID);
 
                 // get the order, Integer.MAX_VALUE by default
+                final String orderSource;
                 Object orderObj = 
reference.getProperty(Constants.SERVICE_RANKING);
                 if (orderObj == null) {
-                    // filter order is defined as lower value has higher 
priority
-                    // while service ranking is the opposite
-                    // In addition we allow different types than Integer
+                    // filter order is defined as lower value has higher
+                    // priority while service ranking is the opposite In
+                    // addition we allow different types than Integer
                     orderObj = 
reference.getProperty(EngineConstants.FILTER_ORDER);
-                    if ( orderObj != null ) {
-                        // we can use 0 as the default as this will be applied 
in
-                        // the next step anyway if this props contains an 
invalid
-                        // value
-                        Integer order = OsgiUtil.toInteger(orderObj, 0);
-                        order = order * -1;
+                    if (orderObj != null) {
+                        // we can use 0 as the default as this will be applied
+                        // in the next step anyway if this props contains an
+                        // invalid value
+                        orderSource = EngineConstants.FILTER_ORDER + "=" + 
orderObj;
+                        orderObj = Integer.valueOf(-1 * 
OsgiUtil.toInteger(orderObj, 0));
+                    } else {
+                        orderSource = "none";
                     }
+                } else {
+                    orderSource = Constants.SERVICE_RANKING + "=" + orderObj;
                 }
-                final int order = (orderObj instanceof Integer)
-                        ? ((Integer) orderObj).intValue()
-                        : 0;
+                final int order = (orderObj instanceof Integer) ? ((Integer) 
orderObj).intValue() : 0;
 
                 // register by scope
                 String[] scopes = OsgiUtil.toStringArray(
@@ -221,13 +224,13 @@ public class ServletFilterManager extend
                         try {
                             FilterChainType type = 
FilterChainType.valueOf(scope.toString());
                             getFilterChain(type).addFilter(filter, serviceId,
-                                order);
+                                order, orderSource);
 
                             if (type == FilterChainType.COMPONENT) {
                                 
getFilterChain(FilterChainType.INCLUDE).addFilter(
-                                    filter, serviceId, order);
+                                    filter, serviceId, order, orderSource);
                                 
getFilterChain(FilterChainType.FORWARD).addFilter(
-                                    filter, serviceId, order);
+                                    filter, serviceId, order, orderSource);
                             }
 
                         } catch (IllegalArgumentException iae) {
@@ -239,7 +242,7 @@ public class ServletFilterManager extend
                         "A Filter (Service ID %s) has been registered without 
a filter.scope property.",
                         reference.getProperty(Constants.SERVICE_ID)));
                     getFilterChain(FilterChainType.REQUEST).addFilter(filter,
-                        serviceId, order);
+                        serviceId, order, orderSource);
                 }
 
             } catch (ServletException ce) {

Modified: 
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/filter/SlingFilterChainHelper.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/filter/SlingFilterChainHelper.java?rev=1596846&r1=1596845&r2=1596846&view=diff
==============================================================================
--- 
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/filter/SlingFilterChainHelper.java
 (original)
+++ 
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/filter/SlingFilterChainHelper.java
 Thu May 22 12:47:10 2014
@@ -33,33 +33,34 @@ import javax.servlet.Filter;
  */
 public class SlingFilterChainHelper {
 
-    SortedSet<FilterListEntry> filterList;
+    private static final Filter[] EMPTY_FILTER_ARRAY = new Filter[0];
 
-    Filter[] filters;
+    private SortedSet<FilterListEntry> filterList;
+
+    private Filter[] filters = EMPTY_FILTER_ARRAY;
 
     SlingFilterChainHelper() {
     }
 
-    public synchronized Filter addFilter(Filter filter,
-            Long filterId, int order) {
-        filters = null;
+    public synchronized Filter addFilter(final Filter filter,
+            final Long filterId, final int order, final String orderSource) {
         if (filterList == null) {
             filterList = new TreeSet<FilterListEntry>();
         }
-        filterList.add(new FilterListEntry(filter, filterId, order));
+        filterList.add(new FilterListEntry(filter, filterId, order, 
orderSource));
+        filters = this.getFilterArray();
         return filter;
     }
-
+/*
     public synchronized Filter[] removeAllFilters() {
         // will be returned after cleaning the lists
         Filter[] removedFilters = getFilters();
 
-        filters = null;
+        filters = EMPTY_FILTER_ARRAY;
         filterList = null;
 
         return removedFilters;
     }
-
     public synchronized Filter removeFilter(Filter filter) {
         if (filterList != null) {
             filters = null;
@@ -67,50 +68,61 @@ public class SlingFilterChainHelper {
                 FilterListEntry test = fi.next();
                 if (test.getFilter().equals(filter)) {
                     fi.remove();
+                    filters = this.getFilterArray();
                     return test.getFilter();
                 }
             }
         }
 
-        // no removed ComponentFilter
+        // no removed filter
         return null;
     }
+*/
 
-    public synchronized boolean removeFilterById(Object filterId) {
+    public synchronized boolean removeFilterById(final Object filterId) {
         if (filterList != null) {
-            filters = null;
             for (Iterator<FilterListEntry> fi = filterList.iterator(); 
fi.hasNext();) {
                 FilterListEntry test = fi.next();
-                if (test.getFitlerId() == filterId
-                    || (test.getFitlerId() != null && 
test.getFitlerId().equals(
+                if (test.getFilterId() == filterId
+                    || (test.getFilterId() != null && 
test.getFilterId().equals(
                         filterId))) {
                     fi.remove();
+                    filters = this.getFilterArray();
                     return true;
                 }
             }
         }
 
-        // no removed ComponentFilter
+        // no removed filter
         return false;
     }
 
     /**
      * Returns the list of <code>Filter</code>s added to this instance
      * or <code>null</code> if no filters have been added.
+     * This method doesn't need to be synced as it is called from synced 
methods.
      */
-    public synchronized Filter[] getFilters() {
-        if (filters == null) {
-            if (filterList != null && !filterList.isEmpty()) {
-                Filter[] tmp = new Filter[filterList.size()];
-                int i = 0;
-                for (FilterListEntry entry : filterList) {
-                    tmp[i] = entry.getFilter();
-                    i++;
-                }
-                filters = tmp;
+    private Filter[] getFilterArray() {
+        if (filterList != null && !filterList.isEmpty()) {
+            final Filter[] tmp = new Filter[filterList.size()];
+            int i = 0;
+            for (FilterListEntry entry : filterList) {
+                tmp[i] = entry.getFilter();
+                i++;
             }
+            return tmp;
         }
-        return filters;
+        return EMPTY_FILTER_ARRAY;
+    }
+
+    /**
+     * Returns the list of <code>Filter</code>s added to this instance
+     * or <code>null</code> if no filters have been added.
+     * This method doesn't need to be synced as it is only
+     * returned the current cached filter array.
+     */
+    public Filter[] getFilters() {
+        return this.filters;
     }
 
     /**
@@ -134,17 +146,20 @@ public class SlingFilterChainHelper {
 
         private final int order;
 
-        FilterListEntry(Filter filter, Long filterId, int order) {
+        private final String orderSource;
+
+        FilterListEntry(final Filter filter, final Long filterId, final int 
order, final String orderSource) {
             this.filter = filter;
             this.filterId = filterId;
             this.order = order;
+            this.orderSource = orderSource;
         }
 
         public Filter getFilter() {
             return filter;
         }
 
-        public Long getFitlerId() {
+        public Long getFilterId() {
             return filterId;
         }
 
@@ -152,22 +167,27 @@ public class SlingFilterChainHelper {
             return order;
         }
 
+        public String getOrderSource() {
+            return orderSource;
+        }
+
         /**
          * Note: this class has a natural ordering that is inconsistent with
          * equals.
          */
-        public int compareTo(FilterListEntry other) {
+        public int compareTo(final FilterListEntry other) {
             if (this == other || equals(other)) {
                 return 0;
             }
 
-            if (order < other.order) {
+            // new service.ranking order (correct)
+            if (order > other.order) {
                 return -1;
-            } else if (order > other.order) {
+            } else if (order < other.order) {
                 return 1;
             }
 
-            // if the filterId is comparable and the other is of the same class
+            // compare filter id (service id)
             if (filterId != null && other.filterId != null) {
                 int comp = filterId.compareTo(other.filterId);
                 if (comp != 0) {
@@ -175,8 +195,8 @@ public class SlingFilterChainHelper {
                 }
             }
 
-            // this is inserted, obj is existing key
-            return 1; // insert after current key
+            // consider equal ranking
+            return 0;
         }
 
         @Override
@@ -187,13 +207,14 @@ public class SlingFilterChainHelper {
             return filter.hashCode();
         }
 
-        public boolean equals(Object obj) {
+        @Override
+        public boolean equals(final Object obj) {
             if (this == obj) {
                 return true;
             }
 
             if (obj instanceof FilterListEntry) {
-                FilterListEntry other = (FilterListEntry) obj;
+                final FilterListEntry other = (FilterListEntry) obj;
                 return getFilter().equals(other.getFilter());
             }
 

Added: 
sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/filter/SlingFilterChainHelperTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/filter/SlingFilterChainHelperTest.java?rev=1596846&view=auto
==============================================================================
--- 
sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/filter/SlingFilterChainHelperTest.java
 (added)
+++ 
sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/filter/SlingFilterChainHelperTest.java
 Thu May 22 12:47:10 2014
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations 
under
+ * the License.
+ */
+package org.apache.sling.engine.impl.filter;
+
+import static org.junit.Assert.assertEquals;
+
+import javax.servlet.Filter;
+
+import org.jmock.Mockery;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Basic tests for the filter chain.
+ */
+@RunWith(JMock.class)
+public class SlingFilterChainHelperTest {
+
+    private final Mockery context = new JUnit4Mockery();
+    @Test public void testOrdering() {
+        final SlingFilterChainHelper chain = new SlingFilterChainHelper();
+
+        chain.addFilter(context.mock(Filter.class, "A"), 1L, 100, "1:100");
+        chain.addFilter(context.mock(Filter.class, "B"), 2L, 100, "2:100");
+        chain.addFilter(context.mock(Filter.class, "C"), 3L, -100, "3:-100");
+        chain.addFilter(context.mock(Filter.class, "D"), 4L, -1000, "4:-1000");
+        chain.addFilter(context.mock(Filter.class, "E"), 5L, 1000, "5:1000");
+
+        final SlingFilterChainHelper.FilterListEntry[] entries = 
chain.getFilterListEntries();
+        assertEquals(5, entries.length);
+        assertEquals("5:1000", entries[0].getOrderSource());
+        assertEquals("1:100", entries[1].getOrderSource());
+        assertEquals("2:100", entries[2].getOrderSource());
+        assertEquals("3:-100", entries[3].getOrderSource());
+        assertEquals("4:-1000", entries[4].getOrderSource());
+    }
+}

Propchange: 
sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/filter/SlingFilterChainHelperTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/filter/SlingFilterChainHelperTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: 
sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/filter/SlingFilterChainHelperTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain


Reply via email to