Author: markt
Date: Mon Feb 13 14:13:27 2017
New Revision: 1782775

URL: http://svn.apache.org/viewvc?rev=1782775&view=rev
Log:
Refactor default JASPIC uthConfigFactory implementation and implement 
notifications.

Added:
    
tomcat/trunk/test/org/apache/catalina/authenticator/jaspic/TestAuthConfigFactoryImpl.java
Modified:
    
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/AuthConfigFactoryImpl.java
    
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/LocalStrings.properties
    tomcat/trunk/webapps/docs/changelog.xml

Modified: 
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/AuthConfigFactoryImpl.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/AuthConfigFactoryImpl.java?rev=1782775&r1=1782774&r2=1782775&view=diff
==============================================================================
--- 
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/AuthConfigFactoryImpl.java
 (original)
+++ 
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/AuthConfigFactoryImpl.java
 Mon Feb 13 14:13:27 2017
@@ -22,7 +22,6 @@ import java.lang.reflect.InvocationTarge
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -52,7 +51,18 @@ public class AuthConfigFactoryImpl exten
 
     private static final String[] EMPTY_STRING_ARRAY = new String[0];
 
-    private final Map<String,RegistrationContextImpl> registrations = new 
ConcurrentHashMap<>();
+    private static String DEFAULT_REGISTRATION_ID = getRegistrationID(null, 
null);
+
+    private final Map<String,RegistrationContextImpl> 
layerAppContextRegistrations =
+            new ConcurrentHashMap<>();
+    private final Map<String,RegistrationContextImpl> appContextRegistrations =
+            new ConcurrentHashMap<>();
+    private final Map<String,RegistrationContextImpl> layerRegistrations =
+            new ConcurrentHashMap<>();
+    // Note: Although there will only ever be a maximum of one entry in this
+    //       Map, use a ConcurrentHashMap for consistency
+    private volatile Map<String,RegistrationContextImpl> defaultRegistration =
+            new ConcurrentHashMap<>(1);
 
 
     public AuthConfigFactoryImpl() {
@@ -63,10 +73,12 @@ public class AuthConfigFactoryImpl exten
     @Override
     public AuthConfigProvider getConfigProvider(String layer, String 
appContext,
             RegistrationListener listener) {
-        String registrationID = getRegistrationID(layer, appContext);
-        RegistrationContextImpl registrationContext = 
registrations.get(registrationID);
+        RegistrationContextImpl registrationContext =
+                findRegistrationContextImpl(layer, appContext);
         if (registrationContext != null) {
-            registrationContext.addListener(null);
+            RegistrationListenerWrapper wrapper = new 
RegistrationListenerWrapper(
+                    layer, appContext, listener);
+            registrationContext.addListener(wrapper);
             return registrationContext.getProvider();
         }
         return null;
@@ -109,8 +121,9 @@ public class AuthConfigFactoryImpl exten
         }
 
         String registrationID = getRegistrationID(layer, appContext);
-        registrations.put(registrationID,
-                new RegistrationContextImpl(layer, appContext, description, 
true, provider, properties));
+        RegistrationContextImpl registrationContextImpl = new 
RegistrationContextImpl(
+                layer, appContext, description, true, provider, properties);
+        addRegistrationContextImpl(layer, appContext, registrationID, 
registrationContextImpl);
         return registrationID;
     }
 
@@ -123,22 +136,115 @@ public class AuthConfigFactoryImpl exten
                     provider.getClass().getName(), layer, appContext));
         }
         String registrationID = getRegistrationID(layer, appContext);
-        registrations.put(registrationID,
-                new RegistrationContextImpl(layer, appContext, description, 
false, provider, null));
+        RegistrationContextImpl registrationContextImpl = new 
RegistrationContextImpl(
+                layer, appContext, description, false, provider, null);
+        addRegistrationContextImpl(layer, appContext, registrationID, 
registrationContextImpl);
         return registrationID;
     }
 
 
+    private void addRegistrationContextImpl(String layer, String appContext,
+            String registrationID, RegistrationContextImpl 
registrationContextImpl) {
+        RegistrationContextImpl previous = null;
+
+        // Add the registration, noting any registration it replaces
+        if (layer != null && appContext != null) {
+            previous = layerAppContextRegistrations.put(registrationID, 
registrationContextImpl);
+        } else if (layer == null && appContext != null) {
+            previous = appContextRegistrations.put(registrationID, 
registrationContextImpl);
+        } else if (layer != null && appContext == null) {
+            previous = layerRegistrations.put(registrationID, 
registrationContextImpl);
+        } else {
+            previous = defaultRegistration.put(registrationID, 
registrationContextImpl);
+        }
+
+        if (previous == null) {
+            // No match with previous registration so need to check listeners
+            // for all less specific registrations to see if they need to be
+            // notified of this new registration. That there is no exact match
+            // with a previous registration allows a few short-cuts to be taken
+            if (layer != null && appContext != null) {
+                // Need to check existing appContext registrations
+                // (and layer and default)
+                // appContext must match
+                RegistrationContextImpl registration =
+                        appContextRegistrations.get(getRegistrationID(null, 
appContext));
+                if (registration != null) {
+                    for (RegistrationListenerWrapper wrapper : 
registration.listeners) {
+                        if (layer.equals(wrapper.getMessageLayer()) &&
+                                appContext.equals(wrapper.getAppContext())) {
+                            registration.listeners.remove(wrapper);
+                            wrapper.listener.notify(wrapper.messageLayer, 
wrapper.appContext);
+                        }
+                    }
+                }
+            }
+            if (appContext != null) {
+                // Need to check existing layer registrations
+                // (and default)
+                // Need to check registrations for all layers
+                for (RegistrationContextImpl registration : 
layerRegistrations.values()) {
+                    for (RegistrationListenerWrapper wrapper : 
registration.listeners) {
+                        if (appContext.equals(wrapper.getAppContext())) {
+                            registration.listeners.remove(wrapper);
+                            wrapper.listener.notify(wrapper.messageLayer, 
wrapper.appContext);
+                        }
+                    }
+                }
+            }
+            if (layer != null || appContext != null) {
+                // Need to check default
+                for (RegistrationContextImpl registration : 
defaultRegistration.values()) {
+                    for (RegistrationListenerWrapper wrapper : 
registration.listeners) {
+                        if (appContext != null && 
appContext.equals(wrapper.getAppContext()) ||
+                                layer != null && 
layer.equals(wrapper.getMessageLayer())) {
+                            registration.listeners.remove(wrapper);
+                            wrapper.listener.notify(wrapper.messageLayer, 
wrapper.appContext);
+                        }
+                    }
+                }
+            }
+        } else {
+            // Replaced an existing registration so need to notify those 
listeners
+            for (RegistrationListenerWrapper wrapper : previous.listeners) {
+                previous.listeners.remove(wrapper);
+                wrapper.listener.notify(wrapper.messageLayer, 
wrapper.appContext);
+            }
+        }
+    }
+
+
     @Override
     public boolean removeRegistration(String registrationID) {
-        return registrations.remove(registrationID) != null;
+        RegistrationContextImpl registration = null;
+        if (DEFAULT_REGISTRATION_ID.equals(registrationID)) {
+            registration = defaultRegistration.remove(registrationID);
+        }
+        if (registration == null) {
+            registration = layerAppContextRegistrations.remove(registrationID);
+        }
+        if (registration == null) {
+            registration =  appContextRegistrations.remove(registrationID);
+        }
+        if (registration == null) {
+            registration = layerRegistrations.remove(registrationID);
+        }
+
+        if (registration == null) {
+            return false;
+        } else {
+            for (RegistrationListenerWrapper wrapper : registration.listeners) 
{
+                wrapper.getListener().notify(wrapper.getMessageLayer(), 
wrapper.getAppContext());
+            }
+            return true;
+        }
     }
 
 
     @Override
     public String[] detachListener(RegistrationListener listener, String 
layer, String appContext) {
         String registrationID = getRegistrationID(layer, appContext);
-        RegistrationContextImpl registrationContext = 
registrations.get(registrationID);
+        RegistrationContextImpl registrationContext = 
findRegistrationContextImpl(layer, appContext);
         if (registrationContext.removeListener(listener)) {
             return new String[] { registrationID };
         }
@@ -148,23 +254,47 @@ public class AuthConfigFactoryImpl exten
 
     @Override
     public String[] getRegistrationIDs(AuthConfigProvider provider) {
+        List<String> result = new ArrayList<>();
         if (provider == null) {
-            return registrations.keySet().toArray(EMPTY_STRING_ARRAY);
+            result.addAll(layerAppContextRegistrations.keySet());
+            result.addAll(appContextRegistrations.keySet());
+            result.addAll(layerRegistrations.keySet());
+            if (defaultRegistration != null) {
+                result.add(DEFAULT_REGISTRATION_ID);
+            }
         } else {
-            List<String> results = new ArrayList<>();
-            for (Entry<String,RegistrationContextImpl> entry : 
registrations.entrySet()) {
-                if (provider.equals(entry.getValue().getProvider())) {
-                    results.add(entry.getKey());
-                }
+            findProvider(provider, layerAppContextRegistrations, result);
+            findProvider(provider, appContextRegistrations, result);
+            findProvider(provider, layerRegistrations, result);
+            findProvider(provider, defaultRegistration, result);
+        }
+        return result.toArray(EMPTY_STRING_ARRAY);
+    }
+
+
+    private void findProvider(AuthConfigProvider provider,
+            Map<String,RegistrationContextImpl> registrations, List<String> 
result) {
+        for (Entry<String,RegistrationContextImpl> entry : 
registrations.entrySet()) {
+            if (provider.equals(entry.getValue().getProvider())) {
+                result.add(entry.getKey());
             }
-            return results.toArray(EMPTY_STRING_ARRAY);
         }
     }
 
 
     @Override
     public RegistrationContext getRegistrationContext(String registrationID) {
-        return registrations.get(registrationID);
+        RegistrationContext result = defaultRegistration.get(registrationID);
+        if (result == null) {
+            result = layerAppContextRegistrations.get(registrationID);
+        }
+        if (result == null) {
+            result = appContextRegistrations.get(registrationID);
+        }
+        if (result == null) {
+            result = layerRegistrations.get(registrationID);
+        }
+        return result;
     }
 
 
@@ -174,8 +304,16 @@ public class AuthConfigFactoryImpl exten
     }
 
 
-    private String getRegistrationID(String layer, String appContext) {
-        return layer + ":" + appContext;
+    private static String getRegistrationID(String layer, String appContext) {
+        if (layer != null && layer.length() == 0) {
+            throw new IllegalArgumentException(
+                    
sm.getString("authConfigFactoryImpl.zeroLengthMessageLayer"));
+        }
+        if (appContext != null && appContext.length() == 0) {
+            throw new IllegalArgumentException(
+                    
sm.getString("authConfigFactoryImpl.zeroLengthAppContext"));
+        }
+        return (layer == null ? "" : layer) + ":" + (appContext == null ? "" : 
appContext);
     }
 
 
@@ -200,24 +338,55 @@ public class AuthConfigFactoryImpl exten
     private void savePersistentRegistrations() {
         synchronized (CONFIG_FILE_LOCK) {
             Providers providers = new Providers();
-            for (Entry<String,RegistrationContextImpl> entry : 
registrations.entrySet()) {
-                if (entry.getValue().isPersistent()) {
-                    Provider provider = new Provider();
-                    provider.setAppContext(entry.getValue().getAppContext());
-                    
provider.setClassName(entry.getValue().getProvider().getClass().getName());
-                    provider.setDescription(entry.getValue().getDescription());
-                    provider.setLayer(entry.getValue().getMessageLayer());
-                    for (Entry<String,String> property : 
entry.getValue().getProperties().entrySet()) {
-                        provider.addProperty(property.getKey(), 
property.getValue());
-                    }
-                    providers.addProvider(provider);
-                }
-            }
+            savePersistentProviders(providers, layerAppContextRegistrations);
+            savePersistentProviders(providers, appContextRegistrations);
+            savePersistentProviders(providers, layerRegistrations);
+            savePersistentProviders(providers, defaultRegistration);
             PersistentProviderRegistrations.writeProviders(providers, 
CONFIG_FILE);
         }
     }
 
 
+    private void savePersistentProviders(Providers providers,
+            Map<String,RegistrationContextImpl> registrations) {
+        for (Entry<String,RegistrationContextImpl> entry : 
registrations.entrySet()) {
+            savePersistentProvider(providers, entry.getValue());
+        }
+    }
+
+
+    private void savePersistentProvider(Providers providers,
+            RegistrationContextImpl registrationContextImpl) {
+        if (registrationContextImpl != null && 
registrationContextImpl.isPersistent()) {
+            Provider provider = new Provider();
+            provider.setAppContext(registrationContextImpl.getAppContext());
+            
provider.setClassName(registrationContextImpl.getProvider().getClass().getName());
+            provider.setDescription(registrationContextImpl.getDescription());
+            provider.setLayer(registrationContextImpl.getMessageLayer());
+            for (Entry<String,String> property : 
registrationContextImpl.getProperties().entrySet()) {
+                provider.addProperty(property.getKey(), property.getValue());
+            }
+            providers.addProvider(provider);
+        }
+    }
+
+
+    private RegistrationContextImpl findRegistrationContextImpl(String layer, 
String appContext) {
+        RegistrationContextImpl result;
+        result = layerAppContextRegistrations.get(getRegistrationID(layer, 
appContext));
+        if (result == null) {
+            result = appContextRegistrations.get(getRegistrationID(null, 
appContext));
+        }
+        if (result == null) {
+            result = layerRegistrations.get(getRegistrationID(layer, null));
+        }
+        if (result == null) {
+            result = defaultRegistration.get(DEFAULT_REGISTRATION_ID);
+        }
+        return result;
+    }
+
+
     private static class RegistrationContextImpl implements 
RegistrationContext {
 
         private RegistrationContextImpl(String messageLayer, String 
appContext, String description,
@@ -240,7 +409,7 @@ public class AuthConfigFactoryImpl exten
         private final boolean persistent;
         private final AuthConfigProvider provider;
         private final Map<String,String> properties;
-        private final List<RegistrationListener> listeners = new 
CopyOnWriteArrayList<>();
+        private final List<RegistrationListenerWrapper> listeners = new 
CopyOnWriteArrayList<>();
 
         @Override
         public String getMessageLayer() {
@@ -270,7 +439,7 @@ public class AuthConfigFactoryImpl exten
         }
 
 
-        private void addListener(RegistrationListener listener) {
+        private void addListener(RegistrationListenerWrapper listener) {
             if (listener != null) {
                 listeners.add(listener);
             }
@@ -284,13 +453,43 @@ public class AuthConfigFactoryImpl exten
 
         private boolean removeListener(RegistrationListener listener) {
             boolean result = false;
-            Iterator<RegistrationListener> iter = listeners.iterator();
-            while (iter.hasNext()) {
-                if (iter.next().equals(listener)) {
-                    iter.remove();
+            for (RegistrationListenerWrapper wrapper : listeners) {
+                if (wrapper.getListener().equals(listener)) {
+                    listeners.remove(wrapper);
                 }
             }
             return result;
         }
     }
+
+
+    private static class RegistrationListenerWrapper {
+
+        private final String messageLayer;
+        private final String appContext;
+        private final RegistrationListener listener;
+
+
+        public RegistrationListenerWrapper(String messageLayer, String 
appContext,
+                RegistrationListener listener) {
+            this.messageLayer = messageLayer;
+            this.appContext = appContext;
+            this.listener = listener;
+        }
+
+
+        public String getMessageLayer() {
+            return messageLayer;
+        }
+
+
+        public String getAppContext() {
+            return appContext;
+        }
+
+
+        public RegistrationListener getListener() {
+            return listener;
+        }
+    }
 }

Modified: 
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/LocalStrings.properties?rev=1782775&r1=1782774&r2=1782775&view=diff
==============================================================================
--- 
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/LocalStrings.properties
 (original)
+++ 
tomcat/trunk/java/org/apache/catalina/authenticator/jaspic/LocalStrings.properties
 Mon Feb 13 14:13:27 2017
@@ -14,6 +14,8 @@
 # limitations under the License.
 
 authConfigFactoryImpl.load=Loading persistent provider registrations from [{0}]
+authConfigFactoryImpl.zeroLengthAppContext=A zero length application context 
name is not valid
+authConfigFactoryImpl.zeroLengthMessageLayer=A zero length message layer name 
is not valid
 authConfigFactoryImpl.registerClass=Registering class [{0}] for layer [{1}] 
and application context [{2}]
 authConfigFactoryImpl.registerInstance=Registering instance of type[{0}] for 
layer [{1}] and application context [{2}]
 

Added: 
tomcat/trunk/test/org/apache/catalina/authenticator/jaspic/TestAuthConfigFactoryImpl.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/authenticator/jaspic/TestAuthConfigFactoryImpl.java?rev=1782775&view=auto
==============================================================================
--- 
tomcat/trunk/test/org/apache/catalina/authenticator/jaspic/TestAuthConfigFactoryImpl.java
 (added)
+++ 
tomcat/trunk/test/org/apache/catalina/authenticator/jaspic/TestAuthConfigFactoryImpl.java
 Mon Feb 13 14:13:27 2017
@@ -0,0 +1,294 @@
+/**
+ *  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.catalina.authenticator.jaspic;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.security.auth.message.config.AuthConfigFactory;
+import javax.security.auth.message.config.AuthConfigProvider;
+import javax.security.auth.message.config.RegistrationListener;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestAuthConfigFactoryImpl {
+
+    @Test
+    public void testRegistrationNullLayer() {
+        doTestResistration(null,  "AC_1",  ":AC_1");
+    }
+
+
+    @Test
+    public void testRegistrationNullAppContext() {
+        doTestResistration("L_1",  null,  "L_1:");
+    }
+
+
+    @Test
+    public void testRegistrationNullLayerAndNullAppContext() {
+        doTestResistration(null,  null,  ":");
+    }
+
+
+    @Test
+    public void testSearchNoMatch01() {
+        doTestSearchOrder("foo", "bar", 1);
+    }
+
+
+    @Test
+    public void testSearchNoMatch02() {
+        doTestSearchOrder(null, "bar", 1);
+    }
+
+
+    @Test
+    public void testSearchNoMatch03() {
+        doTestSearchOrder("foo", null, 1);
+    }
+
+
+    @Test
+    public void testSearchNoMatch04() {
+        doTestSearchOrder(null, null, 1);
+    }
+
+
+    @Test
+    public void testSearchOnlyAppContextMatch01() {
+        doTestSearchOrder("foo", "AC_1", 2);
+    }
+
+
+    @Test
+    public void testSearchOnlyAppContextMatch02() {
+        doTestSearchOrder(null, "AC_1", 2);
+    }
+
+
+    @Test
+    public void testSearchOnlyAppContextMatch03() {
+        doTestSearchOrder("L_2", "AC_1", 2);
+    }
+
+
+    @Test
+    public void testSearchOnlyLayerMatch01() {
+        doTestSearchOrder("L_1", "bar", 3);
+    }
+
+
+    @Test
+    public void testSearchOnlyLayerMatch02() {
+        doTestSearchOrder("L_1", null, 3);
+    }
+
+
+    @Test
+    public void testSearchOnlyLayerMatch03() {
+        doTestSearchOrder("L_1", "AC_2", 3);
+    }
+
+
+    @Test
+    public void testSearchBothMatch() {
+        doTestSearchOrder("L_2", "AC_2", 4);
+    }
+
+
+    private void doTestSearchOrder(String layer, String appContext, int 
expected) {
+        AuthConfigFactory factory = new AuthConfigFactoryImpl();
+        AuthConfigProvider acp1 = new SimpleAuthConfigProvider(null, null);
+        factory.registerConfigProvider(acp1, null, null, "1");
+        AuthConfigProvider acp2 = new SimpleAuthConfigProvider(null, null);
+        factory.registerConfigProvider(acp2, null, "AC_1", "2");
+        AuthConfigProvider acp3 = new SimpleAuthConfigProvider(null, null);
+        factory.registerConfigProvider(acp3, "L_1", null, "3");
+        AuthConfigProvider acp4 = new SimpleAuthConfigProvider(null, null);
+        factory.registerConfigProvider(acp4, "L_2", "AC_2", "4");
+
+        AuthConfigProvider searchResult = factory.getConfigProvider(layer, 
appContext, null);
+        int searchIndex;
+        if (searchResult == acp1) {
+            searchIndex = 1;
+        } else if (searchResult == acp2) {
+            searchIndex = 2;
+        } else if (searchResult == acp3) {
+            searchIndex = 3;
+        } else if (searchResult == acp4) {
+            searchIndex = 4;
+        } else {
+            searchIndex = -1;
+        }
+        Assert.assertEquals(expected, searchIndex);
+    }
+
+
+    private void doTestResistration(String layer, String appContext, String 
expectedRegId) {
+        AuthConfigFactory factory = new AuthConfigFactoryImpl();
+        AuthConfigProvider acp1 = new SimpleAuthConfigProvider(null, null);
+        SimpleRegistrationListener listener = new 
SimpleRegistrationListener(layer, appContext);
+
+        String regId = factory.registerConfigProvider(acp1, layer, appContext, 
null);
+        Assert.assertEquals(expectedRegId, regId);
+
+        factory.getConfigProvider(layer, appContext, listener);
+        factory.removeRegistration(regId);
+        Assert.assertTrue(listener.wasCorrectlyCalled());
+
+        listener.reset();
+        factory.registerConfigProvider(acp1, layer, appContext, null);
+        factory.getConfigProvider(layer, appContext, listener);
+        // Replace it
+        AuthConfigProvider acp2 = new SimpleAuthConfigProvider(null, null);
+        factory.registerConfigProvider(acp2, layer, appContext, null);
+        Assert.assertTrue(listener.wasCorrectlyCalled());
+    }
+
+
+    @Test
+    public void testRegistrationInsertExact01() {
+        doTestRegistrationInsert("L_3", "AC_2", "L_3", "AC_2");
+    }
+
+
+    @Test
+    public void testRegistrationInsertExact02() {
+        doTestRegistrationInsert("L_2", "AC_3", "L_2", "AC_3");
+    }
+
+
+    @Test
+    public void testRegistrationInsertExact03() {
+        doTestRegistrationInsert("L_4", "AC_4", "L_4", "AC_4");
+    }
+
+
+    @Test
+    public void testRegistrationInsertAppContext01() {
+        doTestRegistrationInsert(null, "AC_3", "L_2", "AC_3");
+    }
+
+
+    @Test
+    public void testRegistrationInsertAppContext02() {
+        doTestRegistrationInsert(null, "AC_4", "L_4", "AC_4");
+    }
+
+
+    @Test
+    public void testRegistrationInsertLayer01() {
+        doTestRegistrationInsert("L_4", null, "L_4", "AC_4");
+    }
+
+
+    private void doTestRegistrationInsert(String newLayer, String 
newAppContext,
+            String expectedListenerLayer, String expectedListenerAppContext) {
+        // Set up
+        AuthConfigFactory factory = new AuthConfigFactoryImpl();
+        AuthConfigProvider acp1 = new SimpleAuthConfigProvider(null, null);
+        factory.registerConfigProvider(acp1, "L_1", "AC_1", null);
+        AuthConfigProvider acp2 = new SimpleAuthConfigProvider(null, null);
+        factory.registerConfigProvider(acp2, null, "AC_2", null);
+        AuthConfigProvider acp3 = new SimpleAuthConfigProvider(null, null);
+        factory.registerConfigProvider(acp3, "L_2", null, null);
+        AuthConfigProvider acp4 = new SimpleAuthConfigProvider(null, null);
+        factory.registerConfigProvider(acp4, null, null, null);
+
+        SimpleRegistrationListener listener1 = new 
SimpleRegistrationListener("L_1", "AC_1");
+        factory.getConfigProvider("L_1", "AC_1", listener1);
+        SimpleRegistrationListener listener2 = new 
SimpleRegistrationListener("L_3", "AC_2");
+        factory.getConfigProvider("L_3", "AC_2", listener2);
+        SimpleRegistrationListener listener3 = new 
SimpleRegistrationListener("L_2", "AC_3");
+        factory.getConfigProvider("L_2", "AC_3", listener3);
+        SimpleRegistrationListener listener4 = new 
SimpleRegistrationListener("L_4", "AC_4");
+        factory.getConfigProvider("L_4", "AC_4", listener4);
+
+        List<SimpleRegistrationListener> listeners = new ArrayList<>();
+        listeners.add(listener1);
+        listeners.add(listener2);
+        listeners.add(listener3);
+        listeners.add(listener4);
+
+        // Register a new provider that will impact some existing registrations
+        AuthConfigProvider acpNew = new SimpleAuthConfigProvider(null, null);
+        factory.registerConfigProvider(acpNew, newLayer, newAppContext, null);
+
+        // Check to see if the expected listener fired.
+        for (SimpleRegistrationListener listener : listeners) {
+            if (listener.wasCalled()) {
+                Assert.assertEquals(listener.layer, expectedListenerLayer);
+                Assert.assertEquals(listener.appContext,  
expectedListenerAppContext);
+                Assert.assertTrue(listener.wasCorrectlyCalled());
+            } else {
+                
Assert.assertFalse((listener.layer.equals(expectedListenerLayer) &&
+                        
listener.appContext.equals(expectedListenerAppContext)));
+            }
+        }
+    }
+
+
+    private static class SimpleRegistrationListener implements 
RegistrationListener {
+
+        private final String layer;
+        private final String appContext;
+
+        private boolean called = false;
+        private String layerNotified;
+        private String appContextNotified;
+
+        public SimpleRegistrationListener(String layer, String appContext) {
+            this.layer = layer;
+            this.appContext = appContext;
+        }
+
+        @Override
+        public void notify(String layer, String appContext) {
+            called = true;
+            layerNotified = layer;
+            appContextNotified = appContext;
+        }
+
+
+        public boolean wasCalled() {
+            return called;
+        }
+
+
+        public boolean wasCorrectlyCalled() {
+            return called && areTheSame(layer, layerNotified) &&
+                    areTheSame(appContext, appContextNotified);
+        }
+
+
+        public void reset() {
+            called = false;
+            layerNotified = null;
+            appContextNotified = null;
+        }
+
+
+        private static boolean areTheSame(String a, String b) {
+            if (a == null) {
+                return b == null;
+            }
+            return a.equals(b);
+        }
+    }
+}

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1782775&r1=1782774&r2=1782775&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Mon Feb 13 14:13:27 2017
@@ -75,6 +75,11 @@
         AUTH_HEADER_NAME in SpnegoAuthenticator. Patch provided by Michael
         Osipov. (violetagg)
       </fix>
+      <fix>
+        The default JASPIC <code>AuthConfigFactory</code> now correctly 
notifies
+        registered <code>RegistrationListener</code>s when a new
+        <code>AuthConfigProvider</code> is registered. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to