You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2015/05/25 11:58:47 UTC

svn commit: r1681575 - in /felix/trunk/http/base/src: main/java/org/apache/felix/http/base/internal/registry/ test/java/org/apache/felix/http/base/internal/registry/

Author: cziegeler
Date: Mon May 25 09:58:46 2015
New Revision: 1681575

URL: http://svn.apache.org/r1681575
Log:
FELIX-4860 : Revisit HandlerRegistry implementation. Unify all listener trackers and info objects into a single object. Cleanup registry handling

Added:
    felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/EventListenerRegistryTest.java   (with props)
Modified:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/EventListenerRegistry.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ListenerMap.java
    felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/FilterRegistryTest.java

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/EventListenerRegistry.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/EventListenerRegistry.java?rev=1681575&r1=1681574&r2=1681575&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/EventListenerRegistry.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/EventListenerRegistry.java Mon May 25 09:58:46 2015
@@ -90,33 +90,35 @@ public final class EventListenerRegistry
      */
     public void addListeners(@Nonnull final ListenerHandler handler)
     {
+        final int reason = handler.init();
+
         if ( handler.getListenerInfo().isListenerType(ServletContextListener.class.getName()))
         {
-            this.contextListeners.add(handler);
+            this.contextListeners.add(handler, reason);
         }
         if ( handler.getListenerInfo().isListenerType(ServletContextAttributeListener.class.getName()))
         {
-            this.contextAttributeListeners.add(handler);
+            this.contextAttributeListeners.add(handler, reason);
         }
         if ( handler.getListenerInfo().isListenerType(HttpSessionListener.class.getName()))
         {
-            this.sessionListeners.add(handler);
+            this.sessionListeners.add(handler, reason);
         }
         if ( handler.getListenerInfo().isListenerType(HttpSessionIdListener.class.getName()))
         {
-            this.sessionIdListeners.add(handler);
+            this.sessionIdListeners.add(handler, reason);
         }
         if ( handler.getListenerInfo().isListenerType(HttpSessionAttributeListener.class.getName()))
         {
-            this.sessionAttributeListeners.add(handler);
+            this.sessionAttributeListeners.add(handler, reason);
         }
         if ( handler.getListenerInfo().isListenerType(ServletRequestListener.class.getName()))
         {
-            this.requestListeners.add(handler);
+            this.requestListeners.add(handler, reason);
         }
         if ( handler.getListenerInfo().isListenerType(ServletRequestAttributeListener.class.getName()))
         {
-            this.requestAttributeListeners.add(handler);
+            this.requestAttributeListeners.add(handler, reason);
         }
     }
 
@@ -127,33 +129,39 @@ public final class EventListenerRegistry
      */
     public void removeListeners(@Nonnull final ListenerInfo info)
     {
+        // each listener map returns the same handler, we just need it once to destory
+        ListenerHandler handler = null;
         if ( info.isListenerType(ServletContextListener.class.getName()))
         {
-            this.contextListeners.remove(info);
+            handler = this.contextListeners.remove(info);
         }
         if ( info.isListenerType(ServletContextAttributeListener.class.getName()))
         {
-            this.contextAttributeListeners.remove(info);
+            handler = this.contextAttributeListeners.remove(info);
         }
         if ( info.isListenerType(HttpSessionListener.class.getName()))
         {
-            this.sessionListeners.remove(info);
+            handler = this.sessionListeners.remove(info);
         }
         if ( info.isListenerType(HttpSessionIdListener.class.getName()))
         {
-            this.sessionIdListeners.remove(info);
+            handler = this.sessionIdListeners.remove(info);
         }
         if ( info.isListenerType(HttpSessionAttributeListener.class.getName()))
         {
-            this.sessionAttributeListeners.remove(info);
+            handler = this.sessionAttributeListeners.remove(info);
         }
         if ( info.isListenerType(ServletRequestListener.class.getName()))
         {
-            this.requestListeners.remove(info);
+            handler = this.requestListeners.remove(info);
         }
         if ( info.isListenerType(ServletRequestAttributeListener.class.getName()))
         {
-            this.requestAttributeListeners.remove(info);
+            handler = this.requestAttributeListeners.remove(info);
+        }
+        if ( handler != null )
+        {
+            handler.destroy();
         }
     }
 

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ListenerMap.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ListenerMap.java?rev=1681575&r1=1681574&r2=1681575&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ListenerMap.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ListenerMap.java Mon May 25 09:58:46 2015
@@ -80,9 +80,8 @@ public class ListenerMap<T extends Event
         this.handlers = Collections.emptyList();
     }
 
-    public synchronized void add(final ListenerHandler handler)
+    public synchronized void add(final ListenerHandler handler, final int reason)
     {
-        final int reason = handler.init();
         final ListenerRegistrationStatus<T> status = new ListenerRegistrationStatus<T>(handler, reason);
 
         final List<ListenerRegistrationStatus<T>> newList = new ArrayList<ListenerMap.ListenerRegistrationStatus<T>>(this.handlers);
@@ -91,7 +90,7 @@ public class ListenerMap<T extends Event
         this.handlers = newList;
     }
 
-    public synchronized void remove(final ListenerInfo info)
+    public synchronized ListenerHandler remove(final ListenerInfo info)
     {
         final List<ListenerRegistrationStatus<T>> newList = new ArrayList<ListenerMap.ListenerRegistrationStatus<T>>(this.handlers);
         final Iterator<ListenerRegistrationStatus<T>> i = newList.iterator();
@@ -100,15 +99,13 @@ public class ListenerMap<T extends Event
             final ListenerRegistrationStatus<T> status = i.next();
             if ( status.getHandler().getListenerInfo().equals(info) )
             {
-                if ( status.getResult() == - 1 )
-                {
-                    status.getHandler().destroy();
-                }
                 i.remove();
                 this.handlers = newList;
-                break;
+
+                return status.getResult() == -1 ? status.getHandler() : null;
             }
         }
+        return null;
     }
 
     public ListenerHandler getListenerHandler(@Nonnull final ListenerInfo info)

Added: felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/EventListenerRegistryTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/EventListenerRegistryTest.java?rev=1681575&view=auto
==============================================================================
--- felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/EventListenerRegistryTest.java (added)
+++ felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/EventListenerRegistryTest.java Mon May 25 09:58:46 2015
@@ -0,0 +1,152 @@
+/*
+ * 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.felix.http.base.internal.registry;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import javax.servlet.DispatcherType;
+import javax.servlet.Filter;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+
+import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.apache.felix.http.base.internal.handler.FilterHandler;
+import org.apache.felix.http.base.internal.handler.HttpServiceFilterHandler;
+import org.apache.felix.http.base.internal.runtime.FilterInfo;
+import org.apache.felix.http.base.internal.runtime.dto.FailedDTOHolder;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.runtime.dto.ServletContextDTO;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
+
+public class EventListenerRegistryTest {
+
+    private final FilterRegistry reg = new FilterRegistry();
+
+    private void assertEmpty(final ServletContextDTO dto, final FailedDTOHolder holder)
+    {
+        assertNull(dto.filterDTOs);
+        assertTrue(holder.failedFilterDTOs.isEmpty());
+    }
+
+    private void clear(final ServletContextDTO dto, final FailedDTOHolder holder)
+    {
+        dto.filterDTOs = null;
+        holder.failedFilterDTOs.clear();
+    }
+
+    @Test public void testSingleFilter() throws InvalidSyntaxException, ServletException
+    {
+        final FailedDTOHolder holder = new FailedDTOHolder();
+        final ServletContextDTO dto = new ServletContextDTO();
+
+        // check DTO
+        reg.getRuntimeInfo(dto, holder.failedFilterDTOs);
+        assertEmpty(dto, holder);
+
+        // register filter
+        final FilterHandler h1 = createFilterHandler(1L, 0, "/foo");
+        reg.addFilter(h1);
+
+        verify(h1.getFilter()).init(Matchers.any(FilterConfig.class));
+
+        // one entry in DTO
+        clear(dto, holder);
+        reg.getRuntimeInfo(dto, holder.failedFilterDTOs);
+        assertTrue(holder.failedFilterDTOs.isEmpty());
+        assertNotNull(dto.filterDTOs);
+        assertEquals(1, dto.filterDTOs.length);
+        assertEquals(1, dto.filterDTOs[0].patterns.length);
+        assertEquals("/foo", dto.filterDTOs[0].patterns[0]);
+
+        // remove filter
+        final Filter f = h1.getFilter();
+        reg.removeFilter(h1.getFilterInfo(), true);
+        verify(f).destroy();
+
+        // empty again
+        clear(dto, holder);
+        reg.getRuntimeInfo(dto, holder.failedFilterDTOs);
+        assertEmpty(dto, holder);
+    }
+
+    @Test public void testFilterOrdering() throws InvalidSyntaxException
+    {
+        final FilterHandler h1 = createFilterHandler(1L, 20, "/foo");
+        reg.addFilter(h1);
+        final FilterHandler h2 = createFilterHandler(2L, 10, "/foo");
+        reg.addFilter(h2);
+        final FilterHandler h3 = createFilterHandler(3L, 30, "/foo");
+        reg.addFilter(h3);
+        final FilterHandler h4 = createFilterHandler(4L, 0, "/other");
+        reg.addFilter(h4);
+        final FilterHandler h5 = createFilterHandler(5L, 90, "/foo");
+        reg.addFilter(h5);
+
+        final FilterHandler[] handlers = reg.getFilterHandlers(null, DispatcherType.REQUEST, "/foo");
+        assertEquals(4, handlers.length);
+        assertEquals(h5.getFilterInfo(), handlers[0].getFilterInfo());
+        assertEquals(h3.getFilterInfo(), handlers[1].getFilterInfo());
+        assertEquals(h1.getFilterInfo(), handlers[2].getFilterInfo());
+        assertEquals(h2.getFilterInfo(), handlers[3].getFilterInfo());
+
+        // cleanup
+        reg.removeFilter(h1.getFilterInfo(), true);
+        reg.removeFilter(h2.getFilterInfo(), true);
+        reg.removeFilter(h3.getFilterInfo(), true);
+        reg.removeFilter(h4.getFilterInfo(), true);
+        reg.removeFilter(h5.getFilterInfo(), true);
+    }
+
+    private static FilterInfo createFilterInfo(final long id, final int ranking, final String... paths) throws InvalidSyntaxException
+    {
+        final BundleContext bCtx = mock(BundleContext.class);
+        when(bCtx.createFilter(Matchers.anyString())).thenReturn(null);
+        final Bundle bundle = mock(Bundle.class);
+        when(bundle.getBundleContext()).thenReturn(bCtx);
+
+        final ServiceReference<Filter> ref = mock(ServiceReference.class);
+        when(ref.getBundle()).thenReturn(bundle);
+        when(ref.getProperty(Constants.SERVICE_ID)).thenReturn(id);
+        when(ref.getProperty(Constants.SERVICE_RANKING)).thenReturn(ranking);
+        when(ref.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN)).thenReturn(paths);
+        when(ref.getPropertyKeys()).thenReturn(new String[0]);
+        final FilterInfo si = new FilterInfo(ref);
+
+        return si;
+    }
+
+    private static FilterHandler createFilterHandler(final long id, final int ranking, final String... paths) throws InvalidSyntaxException
+    {
+        final FilterInfo si = createFilterInfo(id, ranking, paths);
+        final ExtServletContext ctx = mock(ExtServletContext.class);
+        final Filter filter = mock(Filter.class);
+
+        return new HttpServiceFilterHandler(ctx, si, filter);
+    }
+}

Propchange: felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/EventListenerRegistryTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/EventListenerRegistryTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Modified: felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/FilterRegistryTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/FilterRegistryTest.java?rev=1681575&r1=1681574&r2=1681575&view=diff
==============================================================================
--- felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/FilterRegistryTest.java (original)
+++ felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/registry/FilterRegistryTest.java Mon May 25 09:58:46 2015
@@ -21,18 +21,17 @@ import static org.junit.Assert.assertNot
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import javax.servlet.DispatcherType;
-import javax.servlet.Filter;
-import javax.servlet.FilterConfig;
+import java.util.EventListener;
+
+import javax.servlet.ServletContextListener;
 import javax.servlet.ServletException;
 
 import org.apache.felix.http.base.internal.context.ExtServletContext;
-import org.apache.felix.http.base.internal.handler.FilterHandler;
-import org.apache.felix.http.base.internal.handler.HttpServiceFilterHandler;
-import org.apache.felix.http.base.internal.runtime.FilterInfo;
+import org.apache.felix.http.base.internal.handler.ListenerHandler;
+import org.apache.felix.http.base.internal.handler.WhiteboardListenerHandler;
+import org.apache.felix.http.base.internal.runtime.ListenerInfo;
 import org.apache.felix.http.base.internal.runtime.dto.FailedDTOHolder;
 import org.junit.Test;
 import org.mockito.Matchers;
@@ -40,113 +39,89 @@ import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceObjects;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.runtime.dto.ServletContextDTO;
-import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
 public class FilterRegistryTest {
 
-    private final FilterRegistry reg = new FilterRegistry();
-
     private void assertEmpty(final ServletContextDTO dto, final FailedDTOHolder holder)
     {
-        assertNull(dto.filterDTOs);
-        assertTrue(holder.failedFilterDTOs.isEmpty());
+        assertNull(dto.listenerDTOs);
+        assertTrue(holder.failedListenerDTOs.isEmpty());
     }
 
     private void clear(final ServletContextDTO dto, final FailedDTOHolder holder)
     {
-        dto.filterDTOs = null;
-        holder.failedFilterDTOs.clear();
+        dto.listenerDTOs = null;
+        holder.failedListenerDTOs.clear();
     }
 
-    @Test public void testSingleFilter() throws InvalidSyntaxException, ServletException
+    @Test public void testSingleListener() throws InvalidSyntaxException, ServletException
     {
+        final EventListenerRegistry reg = new EventListenerRegistry();
         final FailedDTOHolder holder = new FailedDTOHolder();
         final ServletContextDTO dto = new ServletContextDTO();
 
         // check DTO
-        reg.getRuntimeInfo(dto, holder.failedFilterDTOs);
+        reg.getRuntimeInfo(dto, holder.failedListenerDTOs);
         assertEmpty(dto, holder);
 
-        // register filter
-        final FilterHandler h1 = createFilterHandler(1L, 0, "/foo");
-        reg.addFilter(h1);
-
-        verify(h1.getFilter()).init(Matchers.any(FilterConfig.class));
+        // register listener
+        final ListenerHandler h1 = createListenerHandler(1L, 0, ServletContextListener.class);
+        reg.addListeners(h1);
 
         // one entry in DTO
         clear(dto, holder);
-        reg.getRuntimeInfo(dto, holder.failedFilterDTOs);
-        assertTrue(holder.failedFilterDTOs.isEmpty());
-        assertNotNull(dto.filterDTOs);
-        assertEquals(1, dto.filterDTOs.length);
-        assertEquals(1, dto.filterDTOs[0].patterns.length);
-        assertEquals("/foo", dto.filterDTOs[0].patterns[0]);
-
-        // remove filter
-        final Filter f = h1.getFilter();
-        reg.removeFilter(h1.getFilterInfo(), true);
-        verify(f).destroy();
+        reg.getRuntimeInfo(dto, holder.failedListenerDTOs);
+        assertTrue(holder.failedListenerDTOs.isEmpty());
+        assertNotNull(dto.listenerDTOs);
+        assertEquals(1, dto.listenerDTOs.length);
+        assertEquals(1, dto.listenerDTOs[0].types.length);
+        assertEquals(ServletContextListener.class.getName(), dto.listenerDTOs[0].types[0]);
+
+        // remove listener
+        reg.removeListeners(h1.getListenerInfo());
 
         // empty again
         clear(dto, holder);
-        reg.getRuntimeInfo(dto, holder.failedFilterDTOs);
+        reg.getRuntimeInfo(dto, holder.failedListenerDTOs);
         assertEmpty(dto, holder);
     }
 
-    @Test public void testFilterOrdering() throws InvalidSyntaxException
+    private static ListenerInfo createListenerInfo(final long id, final int ranking, final Class<? extends EventListener> type) throws InvalidSyntaxException
     {
-        final FilterHandler h1 = createFilterHandler(1L, 20, "/foo");
-        reg.addFilter(h1);
-        final FilterHandler h2 = createFilterHandler(2L, 10, "/foo");
-        reg.addFilter(h2);
-        final FilterHandler h3 = createFilterHandler(3L, 30, "/foo");
-        reg.addFilter(h3);
-        final FilterHandler h4 = createFilterHandler(4L, 0, "/other");
-        reg.addFilter(h4);
-        final FilterHandler h5 = createFilterHandler(5L, 90, "/foo");
-        reg.addFilter(h5);
-
-        final FilterHandler[] handlers = reg.getFilterHandlers(null, DispatcherType.REQUEST, "/foo");
-        assertEquals(4, handlers.length);
-        assertEquals(h5.getFilterInfo(), handlers[0].getFilterInfo());
-        assertEquals(h3.getFilterInfo(), handlers[1].getFilterInfo());
-        assertEquals(h1.getFilterInfo(), handlers[2].getFilterInfo());
-        assertEquals(h2.getFilterInfo(), handlers[3].getFilterInfo());
-
-        // cleanup
-        reg.removeFilter(h1.getFilterInfo(), true);
-        reg.removeFilter(h2.getFilterInfo(), true);
-        reg.removeFilter(h3.getFilterInfo(), true);
-        reg.removeFilter(h4.getFilterInfo(), true);
-        reg.removeFilter(h5.getFilterInfo(), true);
-    }
+        final String[] typeNames = new String[1];
+        int index = 0;
+        typeNames[index++] = type.getName();
 
-    private static FilterInfo createFilterInfo(final long id, final int ranking, final String... paths) throws InvalidSyntaxException
-    {
         final BundleContext bCtx = mock(BundleContext.class);
         when(bCtx.createFilter(Matchers.anyString())).thenReturn(null);
         final Bundle bundle = mock(Bundle.class);
         when(bundle.getBundleContext()).thenReturn(bCtx);
 
-        final ServiceReference<Filter> ref = mock(ServiceReference.class);
+        final ServiceReference<EventListener> ref = mock(ServiceReference.class);
         when(ref.getBundle()).thenReturn(bundle);
         when(ref.getProperty(Constants.SERVICE_ID)).thenReturn(id);
         when(ref.getProperty(Constants.SERVICE_RANKING)).thenReturn(ranking);
-        when(ref.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN)).thenReturn(paths);
+        when(ref.getProperty(Constants.OBJECTCLASS)).thenReturn(typeNames);
         when(ref.getPropertyKeys()).thenReturn(new String[0]);
-        final FilterInfo si = new FilterInfo(ref);
 
-        return si;
+        final EventListener listener = mock(type);
+        final ServiceObjects<EventListener> so = mock(ServiceObjects.class);
+        when(bCtx.getServiceObjects(ref)).thenReturn(so);
+        when(so.getService()).thenReturn(listener);
+
+        final ListenerInfo info = new ListenerInfo(ref);
+
+        return info;
     }
 
-    private static FilterHandler createFilterHandler(final long id, final int ranking, final String... paths) throws InvalidSyntaxException
+    private static ListenerHandler createListenerHandler(final long id, final int ranking, final Class<? extends EventListener> type) throws InvalidSyntaxException
     {
-        final FilterInfo si = createFilterInfo(id, ranking, paths);
+        final ListenerInfo info = createListenerInfo(id, ranking, type);
         final ExtServletContext ctx = mock(ExtServletContext.class);
-        final Filter filter = mock(Filter.class);
 
-        return new HttpServiceFilterHandler(ctx, si, filter);
+        return new WhiteboardListenerHandler(1L, ctx, info, info.getServiceReference().getBundle().getBundleContext());
     }
 }