Model can now instantiate auth modules

git-svn-id: https://svn.apache.org/repos/asf/geronimo/components/jaspi/trunk@677988 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/AuthConfigFactoryImpl.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/AuthConfigFactoryImpl.java
index de5ec0b..b2b0c47 100644
--- a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/AuthConfigFactoryImpl.java
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/AuthConfigFactoryImpl.java
@@ -25,6 +25,7 @@
 import java.util.Map;

 

 import javax.security.auth.AuthPermission;

+import javax.security.auth.callback.CallbackHandler;

 import javax.security.auth.message.AuthException;

 import javax.security.auth.message.config.AuthConfigFactory;

 import javax.security.auth.message.config.AuthConfigProvider;

@@ -43,13 +44,16 @@
  */

 public class AuthConfigFactoryImpl extends AuthConfigFactory {

 

+    private static final File DEFAULT_CONFIG_FILE = new File("config/jaspi.xml");

+    public static File staticConfigFile = DEFAULT_CONFIG_FILE;

+    public static CallbackHandler staticCallbackHandler;

+

     private static ClassLoader contextClassLoader;

     private JaspiType jaspiType = new JaspiType();

 

     private final ClassLoaderLookup classLoaderLookup;

+    private final CallbackHandler callbackHandler;

     private final File configFile;

-    private static final File DEFAULT_CONFIG_FILE = new File("config/jaspi.xml");

-    public static File staticConfigFile = DEFAULT_CONFIG_FILE;

 

     static {

         contextClassLoader = java.security.AccessController

@@ -60,9 +64,10 @@
                         });

     }

 

-    public AuthConfigFactoryImpl(ClassLoaderLookup classLoaderLookup, File configFile) throws AuthException {

-        JaspiXmlUtil.registerClassLoaderLookup(classLoaderLookup);

+    public AuthConfigFactoryImpl(ClassLoaderLookup classLoaderLookup, CallbackHandler callbackHandler, File configFile) throws AuthException {

+        JaspiXmlUtil.initialize(classLoaderLookup, callbackHandler);

         this.classLoaderLookup = classLoaderLookup;

+        this.callbackHandler = callbackHandler;

         this.configFile = configFile;

         loadConfig();

     }

@@ -73,7 +78,7 @@
             public ClassLoader getClassLoader(String name) {

                 return contextClassLoader;

             }

-        }, staticConfigFile);

+        }, staticCallbackHandler, staticConfigFile);

     }

     

     public synchronized String[] detachListener(RegistrationListener listener, String layer, String appContext) throws SecurityException {

@@ -186,7 +191,7 @@
             }

             ctx.setClassName(className);

             ctx.setProperties(constructorParam);

-            ctx.createAuthConfigProvider(classLoaderLookup);

+            ctx.initialize(classLoaderLookup, callbackHandler);

         } else {

             if (provider == null) {

                 throw new IllegalStateException("No config provider to set");

diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/AuthModuleType.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/AuthModuleType.java
index ad4a8cb..9f04dc2 100644
--- a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/AuthModuleType.java
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/AuthModuleType.java
@@ -10,13 +10,22 @@
 
 import java.io.Serializable;
 import java.util.Map;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.MessagePolicy;
+
+import org.apache.geronimo.components.jaspi.ClassLoaderLookup;
 
 
 /**
@@ -55,14 +64,11 @@
     private final static long serialVersionUID = 12343L;
     @XmlElement(required = true)
     protected String className;
-    @XmlElement(required = true)
+    protected String classLoaderName;
     protected MessagePolicyType requestPolicy;
-    @XmlElement(required = true)
     protected MessagePolicyType responsePolicy;
     @XmlJavaTypeAdapter(StringMapAdapter.class)
     protected Map<String, String> options;
-    @XmlTransient
-    private T authModule;
 
     /**
      * Gets the value of the className property.
@@ -160,11 +166,46 @@
         this.options = value;
     }
 
-    public void createAuthModule(ClassLoader classLoader) {
-        throw new RuntimeException("NYI");
+    public String getClassLoaderName() {
+        return classLoaderName;
     }
 
-    public T getAuthModule() {
+    public void setClassLoaderName(String classLoaderName) {
+        this.classLoaderName = classLoaderName;
+    }
+
+    public T newAuthModule(final ClassLoaderLookup classLoaderLookup, final CallbackHandler callbackHandler) throws AuthException {
+        final ClassLoader classLoader = classLoaderLookup.getClassLoader(classLoaderName);
+        T authModule;
+        try {
+            authModule = java.security.AccessController
+            .doPrivileged(new PrivilegedExceptionAction<T>() {
+                public T run() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, AuthException {
+                    Class<? extends T> cl = (Class<? extends T>) Class.forName(className, true, classLoader);
+                    Constructor<? extends T> cnst = cl.getConstructor();
+                    T authModule = cnst.newInstance();
+                    Method m = cl.getMethod("initialize", MessagePolicy.class, MessagePolicy.class, CallbackHandler.class, Map.class);
+                    MessagePolicy reqPolicy = requestPolicy == null? null:requestPolicy.newMessagePolicy(classLoader);
+                    MessagePolicy respPolicy = responsePolicy == null? null: responsePolicy.newMessagePolicy(classLoader);
+                    m.invoke(authModule, reqPolicy, respPolicy, callbackHandler, options);
+                    return authModule;
+                }
+            });
+        } catch (PrivilegedActionException e) {
+            Exception inner = e.getException();
+            if (inner instanceof InstantiationException) {
+                throw (AuthException) new AuthException("AuthConfigFactory error:"
+                                + inner.getCause().getMessage()).initCause(inner.getCause());
+            } else {
+                throw (AuthException) new AuthException("AuthConfigFactory error: " + inner).initCause(inner);
+            }
+        } catch (Exception e) {
+            throw (AuthException) new AuthException("AuthConfigFactory error: " + e).initCause(e);
+        }
+
+
+
         return authModule;
     }
+
 }
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ClientAuthConfigType.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ClientAuthConfigType.java
index f693f47..68bff90 100644
--- a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ClientAuthConfigType.java
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ClientAuthConfigType.java
@@ -9,19 +9,23 @@
 package org.apache.geronimo.components.jaspi.model;
 
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
+import java.util.HashMap;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import javax.security.auth.message.config.ClientAuthConfig;
 import javax.security.auth.message.config.ClientAuthContext;
 import javax.security.auth.message.AuthException;
 import javax.security.auth.message.MessageInfo;
 import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+import org.apache.geronimo.components.jaspi.ClassLoaderLookup;
 
 
 /**
@@ -56,7 +60,7 @@
     "clientAuthContext"
 })
 public class ClientAuthConfigType
-    implements ClientAuthConfig, Serializable
+    implements Serializable, KeyedObject
 {
 
     private final static long serialVersionUID = 12343L;
@@ -65,7 +69,9 @@
     protected String authenticationContextID;
     @XmlElement(name = "protected")
     protected boolean _protected;
-    protected List<ClientAuthContextType> clientAuthContext;
+    //TODO go back to a map
+    @XmlJavaTypeAdapter(KeyedObjectMapAdapter.class)
+    protected Map<String, ClientAuthContextType> clientAuthContext;
 
     /**
      * Gets the value of the messageLayer property.
@@ -103,19 +109,6 @@
         return appContext;
     }
 
-    public String getAuthContextID(MessageInfo messageInfo) throws IllegalArgumentException {
-        if (authenticationContextID != null) {
-            return authenticationContextID;
-        }
-        for (ClientAuthContextType clientAuthContextType: clientAuthContext) {
-            String authContextID = clientAuthContextType.getAuthenticationContextID(messageInfo);
-            if (authContextID != null) {
-                return authContextID;
-            }
-        }
-        return null;
-    }
-
     /**
      * Sets the value of the appContext property.
      * 
@@ -193,14 +186,87 @@
      * 
      * 
      */
-    public List<ClientAuthContextType> getClientAuthContext() {
+    public Map<String, ClientAuthContextType> getClientAuthContext() {
         if (clientAuthContext == null) {
-            clientAuthContext = new ArrayList<ClientAuthContextType>();
+            clientAuthContext = new HashMap<String, ClientAuthContextType>();
         }
         return this.clientAuthContext;
     }
 
-    public ClientAuthContext getAuthContext(String authContextID, Subject clientSubject, Map properties) throws AuthException {
+
+    //TODO move to ClientAuthContextImpl
+    public String getAuthContextID(MessageInfo messageInfo) throws IllegalArgumentException {
+        if (authenticationContextID != null) {
+            return authenticationContextID;
+        }
+        for (ClientAuthContextType clientAuthContextType: clientAuthContext.values()) {
+            String authContextID = clientAuthContextType.getAuthenticationContextID(messageInfo);
+            if (authContextID != null) {
+                return authContextID;
+            }
+        }
         return null;
     }
+
+    public String getKey() {
+        return ConfigProviderType.getRegistrationKey(messageLayer, appContext);
+    }
+
+    public void initialize(ClassLoaderLookup classLoaderLookup, CallbackHandler callbackHandler) throws AuthException {
+    }
+
+    public boolean isPersistent() {
+        return true;
+    }
+
+    public ClientAuthConfig newClientAuthConfig(String messageLayer, String appContext, ClassLoaderLookup classLoaderLookup, CallbackHandler callbackHandler) throws AuthException {
+        Map<String, ClientAuthContext> authContextMap = new HashMap<String, ClientAuthContext>();
+        for (ClientAuthContextType clientAuthContextType: getClientAuthContext().values()) {
+            if (clientAuthContextType.match(messageLayer, appContext)) {
+                ClientAuthContext clientAuthContext = clientAuthContextType.newClientAuthContext(classLoaderLookup, callbackHandler);
+                String authContextID = clientAuthContextType.getAuthenticationContextID();
+                if (authContextID == null) {
+                    authContextID = getAuthenticationContextID();
+                }
+                if (!authContextMap.containsKey(authContextID)) {
+                    authContextMap.put(authContextID,  clientAuthContext);
+                }
+            }
+        }
+        return new ClientAuthConfigImpl(this, authContextMap);
+    }
+
+    public static class ClientAuthConfigImpl implements ClientAuthConfig {
+
+        private final ClientAuthConfigType clientAuthConfigType;
+        private final Map<String, ClientAuthContext> clientAuthContextMap;
+
+        public ClientAuthConfigImpl(ClientAuthConfigType clientAuthConfigType, Map<String, ClientAuthContext> clientAuthContextMap) {
+            this.clientAuthConfigType = clientAuthConfigType;
+            this.clientAuthContextMap = clientAuthContextMap;
+        }
+
+        public ClientAuthContext getAuthContext(String authContextID, Subject clientSubject, Map properties) throws AuthException {
+            return clientAuthContextMap.get(authContextID);
+        }
+
+        public String getAppContext() {
+            return clientAuthConfigType.getAppContext();
+        }
+
+        public String getAuthContextID(MessageInfo messageInfo) throws IllegalArgumentException {
+            return clientAuthConfigType.getAuthContextID(messageInfo);
+        }
+
+        public String getMessageLayer() {
+            return clientAuthConfigType.getMessageLayer();
+        }
+
+        public boolean isProtected() {
+            return clientAuthConfigType.isProtected();
+        }
+
+        public void refresh() throws AuthException, SecurityException {
+        }
+    }
 }
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ClientAuthContextType.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ClientAuthContextType.java
index 645c251..9a6d460 100644
--- a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ClientAuthContextType.java
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ClientAuthContextType.java
@@ -11,23 +11,27 @@
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.config.ClientAuthContext;
+import javax.security.auth.message.module.ClientAuthModule;
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlType;
-import javax.security.auth.message.config.ClientAuthContext;
-import javax.security.auth.message.MessageInfo;
-import javax.security.auth.message.AuthException;
-import javax.security.auth.message.AuthStatus;
-import javax.security.auth.message.module.ClientAuthModule;
-import javax.security.auth.Subject;
+
+import org.apache.geronimo.components.jaspi.ClassLoaderLookup;
 
 
 /**
  * <p>Java class for clientAuthContextType complex type.
- * 
+ * <p/>
  * <p>The following schema fragment specifies the expected content contained within this class.
- * 
+ * <p/>
  * <pre>
  * &lt;complexType name="clientAuthContextType">
  *   &lt;complexContent>
@@ -42,19 +46,16 @@
  *   &lt;/complexContent>
  * &lt;/complexType>
  * </pre>
- * 
- * 
  */
 @XmlAccessorType(XmlAccessType.FIELD)
 @XmlType(name = "clientAuthContextType", propOrder = {
-    "messageLayer",
-    "appContext",
-    "authenticationContextID",
-    "clientAuthModule"
-})
+        "messageLayer",
+        "appContext",
+        "authenticationContextID",
+        "clientAuthModule"
+        })
 public class ClientAuthContextType
-    implements ClientAuthContext, Serializable
-{
+        implements Serializable, KeyedObject {
 
     private final static long serialVersionUID = 12343L;
     protected String messageLayer;
@@ -65,11 +66,9 @@
 
     /**
      * Gets the value of the messageLayer property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
+     *
+     * @return possible object is
+     *         {@link String }
      */
     public String getMessageLayer() {
         return messageLayer;
@@ -77,11 +76,9 @@
 
     /**
      * Sets the value of the messageLayer property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
+     *
+     * @param value allowed object is
+     *              {@link String }
      */
     public void setMessageLayer(String value) {
         this.messageLayer = value;
@@ -89,11 +86,9 @@
 
     /**
      * Gets the value of the appContext property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
+     *
+     * @return possible object is
+     *         {@link String }
      */
     public String getAppContext() {
         return appContext;
@@ -101,11 +96,9 @@
 
     /**
      * Sets the value of the appContext property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
+     *
+     * @param value allowed object is
+     *              {@link String }
      */
     public void setAppContext(String value) {
         this.appContext = value;
@@ -113,11 +106,9 @@
 
     /**
      * Gets the value of the authenticationContextID property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
+     *
+     * @return possible object is
+     *         {@link String }
      */
     public String getAuthenticationContextID() {
         return authenticationContextID;
@@ -129,11 +120,9 @@
 
     /**
      * Sets the value of the authenticationContextID property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
+     *
+     * @param value allowed object is
+     *              {@link String }
      */
     public void setAuthenticationContextID(String value) {
         this.authenticationContextID = value;
@@ -141,24 +130,23 @@
 
     /**
      * Gets the value of the clientAuthModule property.
-     * 
-     * <p>
+     * <p/>
+     * <p/>
      * This accessor method returns a reference to the live list,
      * not a snapshot. Therefore any modification you make to the
      * returned list will be present inside the JAXB object.
      * This is why there is not a <CODE>set</CODE> method for the clientAuthModule property.
-     * 
-     * <p>
+     * <p/>
+     * <p/>
      * For example, to add a new item, do as follows:
      * <pre>
      *    getClientAuthModule().add(newItem);
      * </pre>
-     * 
-     * 
-     * <p>
+     * <p/>
+     * <p/>
+     * <p/>
      * Objects of the following type(s) are allowed in the list
      * {@link AuthModuleType }
-     * 
      *
      * @return list of client auth module wrappers
      */
@@ -169,44 +157,84 @@
         return this.clientAuthModule;
     }
 
-    public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
-        for (AuthModuleType<ClientAuthModule> authModuleType: getClientAuthModule()) {
-            ClientAuthModule clientAuthModule = authModuleType.getAuthModule();
-            clientAuthModule.cleanSubject(messageInfo, subject);
+
+    public String getKey() {
+        return ConfigProviderType.getRegistrationKey(messageLayer, appContext);
+    }
+
+    public void initialize(ClassLoaderLookup classLoaderLookup, CallbackHandler callbackHandler) throws AuthException {
+    }
+
+    public boolean isPersistent() {
+        return true;
+    }
+
+    public ClientAuthContext newClientAuthContext(ClassLoaderLookup classLoaderLookup, CallbackHandler callbackHandler) throws AuthException {
+        List<ClientAuthModule> clientAuthModules = new ArrayList<ClientAuthModule>();
+        for (AuthModuleType<ClientAuthModule> clientAuthModuleType: clientAuthModule) {
+            ClientAuthModule instance = clientAuthModuleType.newAuthModule(classLoaderLookup, callbackHandler);
+            clientAuthModules.add(instance);
+        }
+        return new ClientAuthContextImpl(clientAuthModules);
+    }
+
+    public boolean match(String messageLayer, String appContext) {
+        if (messageLayer == null) throw new NullPointerException("messageLayer");
+        if (appContext == null) throw new NullPointerException("appContext");
+        if (messageLayer.equals(this.messageLayer)) {
+            return appContext.equals(this.appContext) || this.appContext == null;
+        }
+        if (this.messageLayer == null) {
+            return appContext.equals(this.appContext) || this.appContext == null;
+        }
+        return false;
+    }
+
+    public static class ClientAuthContextImpl implements ClientAuthContext {
+
+        private final List<ClientAuthModule> clientAuthModules;
+
+        public ClientAuthContextImpl(List<ClientAuthModule> clientAuthModules) {
+            this.clientAuthModules = clientAuthModules;
+        }
+
+        public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+            for (ClientAuthModule clientAuthModule : clientAuthModules) {
+                clientAuthModule.cleanSubject(messageInfo, subject);
+            }
+        }
+
+        public AuthStatus secureRequest(MessageInfo messageInfo, Subject clientSubject) throws AuthException {
+            for (ClientAuthModule clientAuthModule : clientAuthModules) {
+                AuthStatus result = clientAuthModule.secureRequest(messageInfo, clientSubject);
+
+                //jaspi spec p 74
+                if (result == AuthStatus.SUCCESS) {
+                    continue;
+                }
+                if (result == AuthStatus.SEND_CONTINUE || result == AuthStatus.FAILURE) {
+                    return result;
+                }
+                throw new AuthException("Invalid AuthStatus " + result + " from client auth module: " + clientAuthModule);
+            }
+            return AuthStatus.SUCCESS;
+        }
+
+        public AuthStatus validateResponse(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+            for (ClientAuthModule clientAuthModule : clientAuthModules) {
+                AuthStatus result = clientAuthModule.validateResponse(messageInfo, clientSubject, serviceSubject);
+
+                //jaspi spec p 74
+                if (result == AuthStatus.SUCCESS) {
+                    continue;
+                }
+                if (result == AuthStatus.SEND_CONTINUE || result == AuthStatus.FAILURE) {
+                    return result;
+                }
+                throw new AuthException("Invalid AuthStatus " + result + " from client auth module: " + clientAuthModule);
+            }
+            return AuthStatus.SUCCESS;
         }
     }
 
-    public AuthStatus secureRequest(MessageInfo messageInfo, Subject clientSubject) throws AuthException {
-        for (AuthModuleType<ClientAuthModule> authModuleType: getClientAuthModule()) {
-            ClientAuthModule clientAuthModule = authModuleType.getAuthModule();
-            AuthStatus result = clientAuthModule.secureRequest(messageInfo, clientSubject);
-
-            //jaspi spec p 74
-            if (result == AuthStatus.SUCCESS) {
-                continue;
-            }
-            if (result == AuthStatus.SEND_CONTINUE || result == AuthStatus.FAILURE) {
-                return result;
-            }
-            throw new AuthException("Invalid AuthStatus " + result + " from client auth module: " + clientAuthModule);
-        }
-        return AuthStatus.SUCCESS;
-    }
-
-    public AuthStatus validateResponse(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
-        for (AuthModuleType<ClientAuthModule> authModuleType: getClientAuthModule()) {
-            ClientAuthModule clientAuthModule = authModuleType.getAuthModule();
-            AuthStatus result = clientAuthModule.validateResponse(messageInfo, clientSubject, serviceSubject);
-
-            //jaspi spec p 74
-            if (result == AuthStatus.SUCCESS) {
-                continue;
-            }
-            if (result == AuthStatus.SEND_CONTINUE || result == AuthStatus.FAILURE) {
-                return result;
-            }
-            throw new AuthException("Invalid AuthStatus " + result + " from client auth module: " + clientAuthModule);
-        }
-        return AuthStatus.SUCCESS;
-    }
 }
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ConfigProviderMapAdapter.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ConfigProviderMapAdapter.java
deleted file mode 100644
index dd5e390..0000000
--- a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ConfigProviderMapAdapter.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.geronimo.components.jaspi.model;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.xml.bind.annotation.adapters.XmlAdapter;
-
-import org.apache.geronimo.components.jaspi.ClassLoaderLookup;
-
-/**
- * @version $Rev$ $Date$
- */
-public class ConfigProviderMapAdapter extends XmlAdapter<ConfigProviderType[], Map<String, ConfigProviderType>> {
-    public static ClassLoaderLookup staticClassLoaderLookup;
-    private final ClassLoaderLookup classLoaderLookup;
-
-    public ConfigProviderMapAdapter(ClassLoaderLookup classLoaderLookup) {
-        this.classLoaderLookup = classLoaderLookup;
-    }
-
-    public ConfigProviderMapAdapter() {
-        if (staticClassLoaderLookup != null) {
-            this.classLoaderLookup = staticClassLoaderLookup;
-        } else {
-            ClassLoader testLoader = Thread.currentThread().getContextClassLoader();
-            final ClassLoader cl = testLoader == null ? ConfigProviderMapAdapter.class.getClassLoader() : testLoader;
-            classLoaderLookup = new ClassLoaderLookup() {
-
-                public ClassLoader getClassLoader(String name) {
-                    return cl;
-                }
-            };
-        }
-    }
-
-    public Map<String, ConfigProviderType> unmarshal(ConfigProviderType[] configProviderTypes) throws Exception {
-        Map<String, ConfigProviderType> map = new HashMap<String, ConfigProviderType>();
-        if (configProviderTypes != null) {
-            for (ConfigProviderType configProviderType : configProviderTypes) {
-                if (configProviderType != null) {
-                    String key = configProviderType.getRegistrationKey();
-                    map.put(key, configProviderType);
-                    configProviderType.createAuthConfigProvider(classLoaderLookup);
-                }
-            }
-        }
-        return map;
-    }
-
-    public ConfigProviderType[] marshal(Map<String, ConfigProviderType> stringConfigProviderTypeMap) throws Exception {
-        List<ConfigProviderType> list = new ArrayList<ConfigProviderType>();
-        for (ConfigProviderType configProviderType : stringConfigProviderTypeMap.values()) {
-            if (configProviderType.isPersistent()) {
-                list.add(configProviderType);
-            }
-        }
-        return list.toArray(new ConfigProviderType[list.size()]);
-    }
-}
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ConfigProviderType.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ConfigProviderType.java
index e261ed7..2311756 100644
--- a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ConfigProviderType.java
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ConfigProviderType.java
@@ -12,6 +12,7 @@
 import java.util.Map;
 import java.util.List;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.security.PrivilegedExceptionAction;
 import java.security.PrivilegedActionException;
 import java.lang.reflect.InvocationTargetException;
@@ -26,7 +27,10 @@
 import javax.security.auth.message.config.AuthConfigFactory;
 import javax.security.auth.message.config.RegistrationListener;
 import javax.security.auth.message.config.AuthConfigProvider;
+import javax.security.auth.message.config.ClientAuthConfig;
+import javax.security.auth.message.config.ServerAuthConfig;
 import javax.security.auth.message.AuthException;
+import javax.security.auth.callback.CallbackHandler;
 
 import org.apache.geronimo.components.jaspi.ClassLoaderLookup;
 
@@ -77,7 +81,7 @@
     "classLoaderName"
 })
 public class ConfigProviderType
-    implements AuthConfigFactory.RegistrationContext, Serializable
+    implements AuthConfigFactory.RegistrationContext, Serializable, KeyedObject
 {
 
     private final static long serialVersionUID = 12343L;
@@ -89,9 +93,11 @@
     @XmlElement(required = true)
     @XmlJavaTypeAdapter(StringMapAdapter.class)
     protected Map<String, String> properties;
-    protected List<ClientAuthConfigType> clientAuthConfig;
-    protected List<ServerAuthConfigType> serverAuthConfig;
-    protected Boolean persistent;
+    @XmlJavaTypeAdapter(KeyedObjectMapAdapter.class)
+    private Map<String, ClientAuthConfigType> clientAuthConfig;
+    @XmlJavaTypeAdapter(KeyedObjectMapAdapter.class)
+    private Map<String, ServerAuthConfigType> serverAuthConfig;
+    protected Boolean persistent = Boolean.FALSE;
     protected String classLoaderName;
 
     @XmlTransient
@@ -251,9 +257,9 @@
      * 
      * 
      */
-    public List<ClientAuthConfigType> getClientAuthConfig() {
+    public Map<String, ClientAuthConfigType> getClientAuthConfig() {
         if (clientAuthConfig == null) {
-            clientAuthConfig = new ArrayList<ClientAuthConfigType>();
+            clientAuthConfig = new HashMap<String, ClientAuthConfigType>();
         }
         return this.clientAuthConfig;
     }
@@ -280,9 +286,9 @@
      * 
      * 
      */
-    public List<ServerAuthConfigType> getServerAuthConfig() {
+    public Map<String, ServerAuthConfigType> getServerAuthConfig() {
         if (serverAuthConfig == null) {
-            serverAuthConfig = new ArrayList<ServerAuthConfigType>();
+            serverAuthConfig = new HashMap<String, ServerAuthConfigType>();
         }
         return this.serverAuthConfig;
     }
@@ -331,37 +337,112 @@
         this.classLoaderName = classLoaderName;
     }
 
-    public void createAuthConfigProvider(ClassLoaderLookup classLoaderLookup) throws AuthException {
-        final ClassLoader classLoader = classLoaderLookup.getClassLoader(classLoaderName);
-        try {
-            provider = java.security.AccessController
-            .doPrivileged(new PrivilegedExceptionAction<AuthConfigProvider>() {
-                public AuthConfigProvider run() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
-                    Class<? extends AuthConfigProvider> cl = (Class<? extends AuthConfigProvider>) Class.forName(className, true, classLoader);
-                    Constructor<? extends AuthConfigProvider> cnst = cl.getConstructor(Map.class);
-                    return cnst.newInstance(properties);
+    public void initialize(ClassLoaderLookup classLoaderLookup, CallbackHandler callbackHandler) throws AuthException {
+        if (className == null) {
+            provider = new ConfigProviderImpl(this, classLoaderLookup);
+        } else {
+            final ClassLoader classLoader = classLoaderLookup.getClassLoader(classLoaderName);
+            try {
+                provider = java.security.AccessController
+                .doPrivileged(new PrivilegedExceptionAction<AuthConfigProvider>() {
+                    public AuthConfigProvider run() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
+                        Class<? extends AuthConfigProvider> cl = (Class<? extends AuthConfigProvider>) Class.forName(className, true, classLoader);
+                        Constructor<? extends AuthConfigProvider> cnst = cl.getConstructor(Map.class);
+                        return cnst.newInstance(properties);
+                    }
+                });
+            } catch (PrivilegedActionException e) {
+                Exception inner = e.getException();
+                if (inner instanceof InstantiationException) {
+                    throw (AuthException) new AuthException("AuthConfigFactory error:"
+                                    + inner.getCause().getMessage()).initCause(inner.getCause());
+                } else {
+                    throw (AuthException) new AuthException("AuthConfigFactory error: " + inner).initCause(inner);
                 }
-            });
-        } catch (PrivilegedActionException e) {
-            Exception inner = e.getException();
-            if (inner instanceof InstantiationException) {
-                throw (AuthException) new AuthException("AuthConfigFactory error:"
-                                + inner.getCause().getMessage()).initCause(inner.getCause());
-            } else {
-                throw (AuthException) new AuthException("AuthConfigFactory error: " + inner).initCause(inner);
+            } catch (Exception e) {
+                throw (AuthException) new AuthException("AuthConfigFactory error: " + e).initCause(e);
             }
-        } catch (Exception e) {
-            throw (AuthException) new AuthException("AuthConfigFactory error: " + e).initCause(e);
         }
-
     }
 
     public static String getRegistrationKey(String layer, String appContext) {
         return layer + "/" + appContext;
     }
 
-    public String getRegistrationKey() {
+    public String getKey() {
         return getRegistrationKey(getMessageLayer(), getAppContext());
     }
 
+    public static class ConfigProviderImpl implements AuthConfigProvider {
+
+        private final ConfigProviderType configProviderType;
+        private final ClassLoaderLookup classLoaderLookup;
+
+        public ConfigProviderImpl(ConfigProviderType configProviderType, ClassLoaderLookup classLoaderLookup) {
+            this.configProviderType = configProviderType;
+            this.classLoaderLookup = classLoaderLookup;
+        }
+
+        /**
+         * spec required constructor
+         * @param properties
+         * @param factory
+         */
+        public ConfigProviderImpl(Map<String, String> properties, AuthConfigFactory factory) {
+            throw new RuntimeException("don't call this");
+        }
+
+        public ClientAuthConfig getClientAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException, SecurityException {
+            if (layer == null) {
+                throw new NullPointerException("messageLayer");
+            }
+            if (appContext == null) {
+                throw new NullPointerException("appContext");
+            }
+            final Map<String, ClientAuthConfigType> configTypeMap = configProviderType.getClientAuthConfig();
+            ClientAuthConfigType ctx = configTypeMap.get(getRegistrationKey(layer, appContext));
+            if (ctx == null) {
+                ctx = configTypeMap.get(getRegistrationKey(null, appContext));
+            }
+            if (ctx == null) {
+                ctx = configTypeMap.get(getRegistrationKey(layer, null));
+            }
+            if (ctx == null) {
+                ctx = configTypeMap.get(getRegistrationKey(null, null));
+            }
+            if (ctx != null) {
+                
+                return ctx.newClientAuthConfig(layer, appContext, classLoaderLookup, handler);
+            }
+            throw new AuthException("No suitable ClientAuthConfig");
+        }
+
+        public ServerAuthConfig getServerAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException, SecurityException {
+            if (layer == null) {
+                throw new NullPointerException("messageLayer");
+            }
+            if (appContext == null) {
+                throw new NullPointerException("appContext");
+            }
+            ServerAuthConfigType ctx = configProviderType.getServerAuthConfig().get(getRegistrationKey(layer, appContext));
+            if (ctx == null) {
+                ctx = configProviderType.getServerAuthConfig().get(getRegistrationKey(null, appContext));
+            }
+            if (ctx == null) {
+                ctx = configProviderType.getServerAuthConfig().get(getRegistrationKey(layer, null));
+            }
+            if (ctx == null) {
+                ctx = configProviderType.getServerAuthConfig().get(getRegistrationKey(null, null));
+            }
+            if (ctx != null) {
+
+                return ctx.newServerAuthConfig(layer, appContext, classLoaderLookup, handler);
+            }
+            throw new AuthException("No suitable ServerAuthConfig");
+        }
+
+        public void refresh() throws AuthException, SecurityException {
+        }
+    }
+
 }
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/JaspiType.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/JaspiType.java
index e12740f..010ed2c 100644
--- a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/JaspiType.java
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/JaspiType.java
@@ -9,8 +9,6 @@
 package org.apache.geronimo.components.jaspi.model;
 
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
 import java.util.HashMap;
 
@@ -51,7 +49,7 @@
 
     private final static long serialVersionUID = 12343L;
 
-    @XmlJavaTypeAdapter(ConfigProviderMapAdapter.class)
+    @XmlJavaTypeAdapter(KeyedObjectMapAdapter.class)
     protected Map<String, ConfigProviderType> configProvider;
 
     /**
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/JaspiXmlUtil.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/JaspiXmlUtil.java
index 04f294a..43d5603 100644
--- a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/JaspiXmlUtil.java
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/JaspiXmlUtil.java
@@ -34,6 +34,7 @@
 import javax.xml.bind.JAXBElement;
 import javax.xml.bind.Unmarshaller;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.security.auth.callback.CallbackHandler;
 
 import org.xml.sax.SAXException;
 import org.apache.geronimo.components.jaspi.ClassLoaderLookup;
@@ -44,7 +45,7 @@
 public class JaspiXmlUtil {
     public static final XMLInputFactory XMLINPUT_FACTORY = XMLInputFactory.newInstance();
     public static final JAXBContext JASPI_CONTEXT;
-    private static ConfigProviderMapAdapter configProviderMapAdapter = new ConfigProviderMapAdapter();
+    private static KeyedObjectMapAdapter configProviderMapAdapter = new KeyedObjectMapAdapter(ConfigProviderType.class);
 
     static {
         try {
@@ -56,8 +57,10 @@
         }
     }
 
-    public static void registerClassLoaderLookup(ClassLoaderLookup classLoaderLookup) {
-        configProviderMapAdapter = new ConfigProviderMapAdapter();
+    public static void initialize(ClassLoaderLookup classLoaderLookup, CallbackHandler callbackHandler) {
+//        configProviderMapAdapter = new KeyedObjectMapAdapter<ConfigProviderType>(classLoaderLookup, callbackHandler, ConfigProviderType.class);
+        KeyedObjectMapAdapter.staticClassLoaderLookup = classLoaderLookup;
+        KeyedObjectMapAdapter.staticCallbackHandler = callbackHandler;
     }
 
     public static void writeJaspi(JaspiType metadata, Writer out) throws XMLStreamException, JAXBException {
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/KeyedObject.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/KeyedObject.java
new file mode 100644
index 0000000..b3c2305
--- /dev/null
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/KeyedObject.java
@@ -0,0 +1,35 @@
+/*
+ * 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.geronimo.components.jaspi.model;
+
+import javax.security.auth.message.AuthException;
+import javax.security.auth.callback.CallbackHandler;
+
+import org.apache.geronimo.components.jaspi.ClassLoaderLookup;
+
+/**
+ * @version $Rev:$ $Date:$
+ */
+public interface KeyedObject {
+    String getKey();
+    void initialize(ClassLoaderLookup classLoaderLookup, CallbackHandler callbackHandler) throws AuthException;
+    boolean isPersistent();
+}
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/KeyedObjectMapAdapter.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/KeyedObjectMapAdapter.java
new file mode 100644
index 0000000..b1edf27
--- /dev/null
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/KeyedObjectMapAdapter.java
@@ -0,0 +1,94 @@
+/*
+ * 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.geronimo.components.jaspi.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.lang.reflect.Array;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import javax.security.auth.callback.CallbackHandler;
+
+import org.apache.geronimo.components.jaspi.ClassLoaderLookup;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class KeyedObjectMapAdapter<T extends KeyedObject> extends XmlAdapter<T[], Map<String, T>> {
+    public static ClassLoaderLookup staticClassLoaderLookup;
+    public static CallbackHandler staticCallbackHandler;
+    private final ClassLoaderLookup classLoaderLookup;
+    private final CallbackHandler callbackHandler;
+    private final Class<T> type;
+
+    public KeyedObjectMapAdapter(ClassLoaderLookup classLoaderLookup, CallbackHandler callbackHandler, Class<T> type) {
+        this.classLoaderLookup = classLoaderLookup;
+        this.callbackHandler = callbackHandler;
+        this.type = type;
+    }
+
+    public KeyedObjectMapAdapter(Class<T> type) {
+        if (staticClassLoaderLookup != null) {
+            this.classLoaderLookup = staticClassLoaderLookup;
+        } else {
+            ClassLoader testLoader = Thread.currentThread().getContextClassLoader();
+            final ClassLoader cl = testLoader == null ? KeyedObjectMapAdapter.class.getClassLoader() : testLoader;
+            classLoaderLookup = new ClassLoaderLookup() {
+
+                public ClassLoader getClassLoader(String name) {
+                    return cl;
+                }
+            };
+        }
+        this.type = type;
+        callbackHandler = staticCallbackHandler;
+    }
+
+    public Map<String, T> unmarshal(T[] configProviderTypes) throws Exception {
+        Map<String, T> map = new HashMap<String, T>();
+        if (configProviderTypes != null) {
+            for (T configProviderType : configProviderTypes) {
+                if (configProviderType != null) {
+                    String key = configProviderType.getKey();
+                    map.put(key, configProviderType);
+                    configProviderType.initialize(classLoaderLookup, callbackHandler);
+                }
+            }
+        }
+        return map;
+    }
+
+    public T[] marshal(Map<String, T> stringConfigProviderTypeMap) throws Exception {
+        if (stringConfigProviderTypeMap == null) {
+            return null;
+        }
+        List<T> list = new ArrayList<T>();
+        for (T configProviderType : stringConfigProviderTypeMap.values()) {
+            if (configProviderType.isPersistent()) {
+                list.add(configProviderType);
+            }
+        }
+        T[] array = (T[]) Array.newInstance(type, list.size());
+        return list.toArray(array);
+    }
+}
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/MessagePolicyType.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/MessagePolicyType.java
index c0d88d3..2bd5df9 100644
--- a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/MessagePolicyType.java
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/MessagePolicyType.java
@@ -15,6 +15,8 @@
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlType;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.AuthException;
 
 
 /**
@@ -87,7 +89,7 @@
      *     {@link Boolean }
      *     
      */
-    public Boolean isMandatory() {
+    public boolean isMandatory() {
         return mandatory;
     }
 
@@ -99,8 +101,20 @@
      *     {@link Boolean }
      *     
      */
-    public void setMandatory(Boolean value) {
+    public void setMandatory(boolean value) {
         this.mandatory = value;
     }
 
+    public MessagePolicy newMessagePolicy(ClassLoader cl) throws AuthException {
+        if (targetPolicy == null || targetPolicy.size() == 0) {
+            return null;
+        }
+        MessagePolicy.TargetPolicy[] targetPolicies = new MessagePolicy.TargetPolicy[targetPolicy.size()];
+        int i = 0;
+        for (TargetPolicyType targetPolicyType: targetPolicy) {
+            targetPolicies[i++] = targetPolicyType.newTargetPolicy(cl);
+        }
+        return new MessagePolicy(targetPolicies, mandatory);
+    }
+
 }
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ProtectionPolicyType.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ProtectionPolicyType.java
index 45c364a..85f8128 100644
--- a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ProtectionPolicyType.java
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ProtectionPolicyType.java
@@ -9,10 +9,17 @@
 package org.apache.geronimo.components.jaspi.model;
 
 import java.io.Serializable;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Constructor;
+
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlType;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.AuthException;
 
 
 /**
@@ -70,4 +77,27 @@
         this.className = value;
     }
 
+    public MessagePolicy.ProtectionPolicy newProtectionPolicy(final ClassLoader classLoader) throws AuthException {
+        try {
+            return java.security.AccessController
+            .doPrivileged(new PrivilegedExceptionAction<MessagePolicy.ProtectionPolicy>() {
+                public MessagePolicy.ProtectionPolicy run() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
+                    Class<? extends MessagePolicy.ProtectionPolicy> cl = (Class<? extends MessagePolicy.ProtectionPolicy>) Class.forName(className, true, classLoader);
+                    Constructor<? extends MessagePolicy.ProtectionPolicy> cnst = cl.getConstructor();
+                    MessagePolicy.ProtectionPolicy target = cnst.newInstance();
+                    return target;
+                }
+            });
+        } catch (PrivilegedActionException e) {
+            Exception inner = e.getException();
+            if (inner instanceof InstantiationException) {
+                throw (AuthException) new AuthException("AuthConfigFactory error:"
+                                + inner.getCause().getMessage()).initCause(inner.getCause());
+            } else {
+                throw (AuthException) new AuthException("AuthConfigFactory error: " + inner).initCause(inner);
+            }
+        } catch (Exception e) {
+            throw (AuthException) new AuthException("AuthConfigFactory error: " + e).initCause(e);
+        }
+    }
 }
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ServerAuthConfigType.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ServerAuthConfigType.java
index 372755c..16fcfad 100644
--- a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ServerAuthConfigType.java
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ServerAuthConfigType.java
@@ -9,19 +9,23 @@
 package org.apache.geronimo.components.jaspi.model;
 
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
+import java.util.HashMap;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import javax.security.auth.message.config.ServerAuthConfig;
 import javax.security.auth.message.config.ServerAuthContext;
 import javax.security.auth.message.AuthException;
 import javax.security.auth.message.MessageInfo;
 import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+
+import org.apache.geronimo.components.jaspi.ClassLoaderLookup;
 
 
 /**
@@ -56,7 +60,7 @@
     "serverAuthContext"
 })
 public class ServerAuthConfigType
-    implements ServerAuthConfig, Serializable
+    implements Serializable, KeyedObject
 {
 
     private final static long serialVersionUID = 12343L;
@@ -65,7 +69,8 @@
     protected String authenticationContextID;
     @XmlElement(name = "protected")
     protected boolean _protected;
-    protected List<ServerAuthContextType> serverAuthContext;
+    @XmlJavaTypeAdapter(KeyedObjectMapAdapter.class)
+    protected Map<String, ServerAuthContextType> serverAuthContext;
 
     /**
      * Gets the value of the messageLayer property.
@@ -107,7 +112,7 @@
         if (authenticationContextID != null) {
             return authenticationContextID;
         }
-        for (ServerAuthContextType serverAuthContextType: serverAuthContext) {
+        for (ServerAuthContextType serverAuthContextType: serverAuthContext.values()) {
             String authContextID = serverAuthContextType.getAuthenticationContextID(messageInfo);
             if (authContextID != null) {
                 return authContextID;
@@ -193,14 +198,81 @@
      * 
      * 
      */
-    public List<ServerAuthContextType> getServerAuthContext() {
+    public Map<String, ServerAuthContextType> getServerAuthContext() {
         if (serverAuthContext == null) {
-            serverAuthContext = new ArrayList<ServerAuthContextType>();
+            serverAuthContext = new HashMap<String, ServerAuthContextType>();
         }
         return this.serverAuthContext;
     }
 
     public ServerAuthContext getAuthContext(String authContextID, Subject serviceSubject, Map properties) throws AuthException {
+        //see page 136  We are going to ignore the clientSubject and properties for now.
+        for (ServerAuthContextType serverAuthContext: getServerAuthContext().values()) {
+            if (serverAuthContext.getAuthenticationContextID().equals(authContextID)) {
+                return serverAuthContext.getServerAuthContext();
+            }
+        }
         return null;
     }
+    public String getKey() {
+        return ConfigProviderType.getRegistrationKey(messageLayer, appContext);
+    }
+
+    public void initialize(ClassLoaderLookup classLoaderLookup, CallbackHandler callbackHandler) throws AuthException {
+    }
+
+    public boolean isPersistent() {
+        return true;
+    }
+
+    public ServerAuthConfig newServerAuthConfig(String messageLayer, String appContext, ClassLoaderLookup classLoaderLookup, CallbackHandler callbackHandler) throws AuthException {
+        Map<String, ServerAuthContext> authContextMap = new HashMap<String, ServerAuthContext>();
+        for (ServerAuthContextType serverAuthContextType: getServerAuthContext().values()) {
+            if (serverAuthContextType.match(messageLayer, appContext)) {
+                ServerAuthContext serverAuthContext = serverAuthContextType.newServerAuthContext(classLoaderLookup, callbackHandler);
+                String authContextID = serverAuthContextType.getAuthenticationContextID();
+                if (authContextID == null) {
+                    authContextID = getAuthenticationContextID();
+                }
+                if (!authContextMap.containsKey(authContextID)) {
+                    authContextMap.put(authContextID,  serverAuthContext);
+                }
+            }
+        }
+        return new ServerAuthConfigImpl(this, authContextMap);
+    }
+
+    public static class ServerAuthConfigImpl implements ServerAuthConfig {
+
+        private final ServerAuthConfigType serverAuthConfigType;
+        private final Map<String, ServerAuthContext> serverAuthContextMap;
+
+        public ServerAuthConfigImpl(ServerAuthConfigType serverAuthConfigType, Map<String, ServerAuthContext> serverAuthContextMap) {
+            this.serverAuthConfigType = serverAuthConfigType;
+            this.serverAuthContextMap = serverAuthContextMap;
+        }
+
+        public ServerAuthContext getAuthContext(String authContextID, Subject serverSubject, Map properties) throws AuthException {
+            return serverAuthContextMap.get(authContextID);
+        }
+
+        public String getAppContext() {
+            return serverAuthConfigType.getAppContext();
+        }
+
+        public String getAuthContextID(MessageInfo messageInfo) throws IllegalArgumentException {
+            return serverAuthConfigType.getAuthContextID(messageInfo);
+        }
+
+        public String getMessageLayer() {
+            return serverAuthConfigType.getMessageLayer();
+        }
+
+        public boolean isProtected() {
+            return serverAuthConfigType.isProtected();
+        }
+
+        public void refresh() throws AuthException, SecurityException {
+        }
+    }
 }
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ServerAuthContextType.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ServerAuthContextType.java
index 2e5c000..7d58f55 100644
--- a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ServerAuthContextType.java
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ServerAuthContextType.java
@@ -13,6 +13,7 @@
 import java.util.List;
 
 import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.message.AuthException;
 import javax.security.auth.message.AuthStatus;
 import javax.security.auth.message.MessageInfo;
@@ -21,8 +22,10 @@
 import javax.security.auth.message.config.ServerAuthContext;
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.apache.geronimo.components.jaspi.ClassLoaderLookup;
 
 
 /**
@@ -53,15 +56,17 @@
         "serverAuthModule"
         })
 public class ServerAuthContextType
-        implements ServerAuthContext, Serializable {
+        implements Serializable, KeyedObject {
 
     private final static long serialVersionUID = 12343L;
     protected String messageLayer;
     protected String appContext;
-    @XmlElement(required = true)
     protected String authenticationContextID;
     protected List<AuthModuleType<ServerAuthModule>> serverAuthModule;
 
+    @XmlTransient
+    private ServerAuthContext serverAuthContext;
+
     /**
      * Gets the value of the messageLayer property.
      *
@@ -153,44 +158,94 @@
         return this.serverAuthModule;
     }
 
-    public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
-        for (AuthModuleType<ServerAuthModule> authModuleType: getServerAuthModule()) {
-            ServerAuthModule serverAuthModule = authModuleType.getAuthModule();
-            serverAuthModule.cleanSubject(messageInfo, subject);
-        }
+    public String getKey() {
+        return ConfigProviderType.getRegistrationKey(messageLayer, appContext);
     }
 
-    public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
-        for (AuthModuleType<ServerAuthModule> authModuleType: getServerAuthModule()) {
-            ServerAuthModule serverAuthModule = authModuleType.getAuthModule();
-            AuthStatus result = serverAuthModule.secureResponse(messageInfo, serviceSubject);
-
-            //jaspi spec p 86
-            if (result == AuthStatus.SEND_SUCCESS) {
-                continue;
-            }
-            if (result == AuthStatus.SEND_CONTINUE || result == AuthStatus.SEND_FAILURE) {
-                return result;
-            }
-            throw new AuthException("Invalid AuthStatus " + result + " from server auth module: " + serverAuthModule);
+    public void initialize(ClassLoaderLookup classLoaderLookup, CallbackHandler callbackHandler) throws AuthException {
+        List<ServerAuthModule> serverAuthModules = new ArrayList<ServerAuthModule>();
+        for (AuthModuleType<ServerAuthModule> serverAuthModuleType: serverAuthModule) {
+            ServerAuthModule instance = serverAuthModuleType.newAuthModule(classLoaderLookup, callbackHandler);
+            serverAuthModules.add(instance);
         }
-        return AuthStatus.SEND_SUCCESS;
+        serverAuthContext = new ServerAuthContextImpl(serverAuthModules);
     }
 
-    public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
-        for (AuthModuleType<ServerAuthModule> authModuleType: getServerAuthModule()) {
-            ServerAuthModule serverAuthModule = authModuleType.getAuthModule();
-            AuthStatus result = serverAuthModule.validateRequest(messageInfo, clientSubject, serviceSubject);
-
-            //jaspi spec p 88
-            if (result == AuthStatus.SUCCESS) {
-                continue;
-            }
-            if (result == AuthStatus.SEND_SUCCESS || result == AuthStatus.SEND_CONTINUE || result == AuthStatus.FAILURE) {
-                return result;
-            }
-            throw new AuthException("Invalid AuthStatus " + result + " from server auth module: " + serverAuthModule);
-        }
-        return AuthStatus.SUCCESS;
+    public boolean isPersistent() {
+        return true;
     }
+
+    public ServerAuthContext getServerAuthContext() {
+        return serverAuthContext;
+    }
+
+    public ServerAuthContext newServerAuthContext(ClassLoaderLookup classLoaderLookup, CallbackHandler callbackHandler) throws AuthException {
+        List<ServerAuthModule> serverAuthModules = new ArrayList<ServerAuthModule>();
+        for (AuthModuleType<ServerAuthModule> serverAuthModuleType: serverAuthModule) {
+            ServerAuthModule instance = serverAuthModuleType.newAuthModule(classLoaderLookup, callbackHandler);
+            serverAuthModules.add(instance);
+        }
+        return new ServerAuthContextImpl(serverAuthModules);
+    }
+
+    public boolean match(String messageLayer, String appContext) {
+        if (messageLayer == null) throw new NullPointerException("messageLayer");
+        if (appContext == null) throw new NullPointerException("appContext");
+        if (messageLayer.equals(this.messageLayer)) {
+            return appContext.equals(this.appContext) || this.appContext == null;
+        }
+        if (this.messageLayer == null) {
+            return appContext.equals(this.appContext) || this.appContext == null;
+        }
+        return false;
+    }
+
+    public static class ServerAuthContextImpl implements ServerAuthContext {
+
+        private final List<ServerAuthModule> serverAuthModules;
+
+        public ServerAuthContextImpl(List<ServerAuthModule> serverAuthModules) {
+            this.serverAuthModules = serverAuthModules;
+        }
+
+        public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+            for (ServerAuthModule serverAuthModule : serverAuthModules) {
+                serverAuthModule.cleanSubject(messageInfo, subject);
+            }
+        }
+
+        public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+            for (ServerAuthModule serverAuthModule : serverAuthModules) {
+                AuthStatus result = serverAuthModule.secureResponse(messageInfo, serviceSubject);
+
+                //jaspi spec p 86
+                if (result == AuthStatus.SEND_SUCCESS) {
+                    continue;
+                }
+                if (result == AuthStatus.SEND_CONTINUE || result == AuthStatus.SEND_FAILURE) {
+                    return result;
+                }
+                throw new AuthException("Invalid AuthStatus " + result + " from server auth module: " + serverAuthModule);
+            }
+            return AuthStatus.SEND_SUCCESS;
+        }
+
+        public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+            for (ServerAuthModule serverAuthModule : serverAuthModules) {
+                AuthStatus result = serverAuthModule.validateRequest(messageInfo, clientSubject, serviceSubject);
+
+                //jaspi spec p 88
+                if (result == AuthStatus.SUCCESS) {
+                    continue;
+                }
+                if (result == AuthStatus.SEND_SUCCESS || result == AuthStatus.SEND_CONTINUE || result == AuthStatus.FAILURE) {
+                    return result;
+                }
+                throw new AuthException("Invalid AuthStatus " + result + " from server auth module: " + serverAuthModule);
+            }
+            return AuthStatus.SUCCESS;
+        }
+
+    }
+
 }
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/TargetPolicyType.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/TargetPolicyType.java
index 0611eb9..235e9bb 100644
--- a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/TargetPolicyType.java
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/TargetPolicyType.java
@@ -11,10 +11,20 @@
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlType;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.callback.CallbackHandler;
 
 
 /**
@@ -104,4 +114,12 @@
         return this.target;
     }
 
+    public MessagePolicy.TargetPolicy newTargetPolicy(ClassLoader cl) throws AuthException {
+        MessagePolicy.Target[] targets = new MessagePolicy.Target[getTarget().size()];
+        int i = 0;
+        for (TargetType targetType: getTarget()) {
+            targets[i++] = targetType.newTarget(cl);
+        }
+        return new MessagePolicy.TargetPolicy(targets, protectionPolicy.newProtectionPolicy(cl));
+    }
 }
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/TargetType.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/TargetType.java
index af40ec1..31d0819 100644
--- a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/TargetType.java
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/TargetType.java
@@ -9,10 +9,20 @@
 package org.apache.geronimo.components.jaspi.model;
 
 import java.io.Serializable;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Map;
+
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlType;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.callback.CallbackHandler;
 
 
 /**
@@ -70,4 +80,29 @@
         this.className = value;
     }
 
+    public MessagePolicy.Target newTarget(final ClassLoader classLoader) throws AuthException {
+        try {
+            return java.security.AccessController
+            .doPrivileged(new PrivilegedExceptionAction<MessagePolicy.Target>() {
+                public MessagePolicy.Target run() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
+                    Class<? extends MessagePolicy.Target> cl = (Class<? extends MessagePolicy.Target>) Class.forName(className, true, classLoader);
+                    Constructor<? extends MessagePolicy.Target> cnst = cl.getConstructor();
+                    MessagePolicy.Target target = cnst.newInstance();
+                    return target;
+                }
+            });
+        } catch (PrivilegedActionException e) {
+            Exception inner = e.getException();
+            if (inner instanceof InstantiationException) {
+                throw (AuthException) new AuthException("AuthConfigFactory error:"
+                                + inner.getCause().getMessage()).initCause(inner.getCause());
+            } else {
+                throw (AuthException) new AuthException("AuthConfigFactory error: " + inner).initCause(inner);
+            }
+        } catch (Exception e) {
+            throw (AuthException) new AuthException("AuthConfigFactory error: " + e).initCause(e);
+        }
+        
+    }
+
 }
diff --git a/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/AuthModuleTypeJAXB.java b/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/AuthModuleTypeJAXB.java
index d86cd2e..cd5539e 100644
--- a/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/AuthModuleTypeJAXB.java
+++ b/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/AuthModuleTypeJAXB.java
@@ -33,6 +33,7 @@
     public final static AuthModuleTypeJAXB<ServerAuthModule> SERVER_INSTANCE = new AuthModuleTypeJAXB<ServerAuthModule>();
     private final static LifecycleCallback lifecycleCallback = new LifecycleCallback(AuthModuleType.class);
     private final static FieldAccessor<AuthModuleType, String> authModuleTypeClassName = new FieldAccessor<AuthModuleType, String>(AuthModuleType.class, "className");
+    private final static FieldAccessor<AuthModuleType, String> authModuleTypeClassLoaderName = new FieldAccessor<AuthModuleType, String>(AuthModuleType.class, "classLoaderName");
     private final static FieldAccessor<AuthModuleType, MessagePolicyType> authModuleTypeRequestPolicy = new FieldAccessor<AuthModuleType, MessagePolicyType>(AuthModuleType.class, "requestPolicy");
     private final static FieldAccessor<AuthModuleType, MessagePolicyType> authModuleTypeResponsePolicy = new FieldAccessor<AuthModuleType, MessagePolicyType>(AuthModuleType.class, "responsePolicy");
     private final static FieldAccessor<AuthModuleType, Map<String, String>> authModuleTypeOptions = new FieldAccessor<AuthModuleType, Map<String, String>>(AuthModuleType.class, "options");
@@ -103,6 +104,10 @@
                 // ELEMENT: className
                 String className = elementReader.getElementAsString();
                 authModuleTypeClassName.setObject(reader, context, authModuleType, className);
+            } else if (("classLoaderName" == elementReader.getLocalName())&&("http://geronimo.apache.org/xml/ns/geronimo-jaspi" == elementReader.getNamespaceURI())) {
+                // ELEMENT: classLoaderName
+                String classLoaderName = elementReader.getElementAsString();
+                authModuleTypeClassLoaderName.setObject(reader, context, authModuleType, classLoaderName);
             } else if (("requestPolicy" == elementReader.getLocalName())&&("http://geronimo.apache.org/xml/ns/geronimo-jaspi" == elementReader.getNamespaceURI())) {
                 // ELEMENT: requestPolicy
                 MessagePolicyType requestPolicy = readMessagePolicyType(elementReader, context);
diff --git a/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ClientAuthConfigTypeJAXB.java b/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ClientAuthConfigTypeJAXB.java
index 7ad8319..557ec26 100644
--- a/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ClientAuthConfigTypeJAXB.java
+++ b/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ClientAuthConfigTypeJAXB.java
@@ -3,6 +3,8 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+
 import javax.xml.XMLConstants;
 import javax.xml.namespace.QName;
 import com.envoisolutions.sxc.jaxb.FieldAccessor;
@@ -14,6 +16,7 @@
 import com.envoisolutions.sxc.util.XoXMLStreamWriter;
 import org.apache.geronimo.components.jaspi.model.ClientAuthConfigType;
 import org.apache.geronimo.components.jaspi.model.ClientAuthContextType;
+import org.apache.geronimo.components.jaspi.model.KeyedObjectMapAdapter;
 
 
 import static sxc.org.apache.geronimo.components.jaspi.model.ClientAuthContextTypeJAXB.readClientAuthContextType;
@@ -32,7 +35,8 @@
     private final static FieldAccessor<ClientAuthConfigType, String> clientAuthConfigTypeAppContext = new FieldAccessor<ClientAuthConfigType, String>(ClientAuthConfigType.class, "appContext");
     private final static FieldAccessor<ClientAuthConfigType, String> clientAuthConfigTypeAuthenticationContextID = new FieldAccessor<ClientAuthConfigType, String>(ClientAuthConfigType.class, "authenticationContextID");
     private final static FieldAccessor<ClientAuthConfigType, Boolean> clientAuthConfigType_protected = new FieldAccessor<ClientAuthConfigType, Boolean>(ClientAuthConfigType.class, "_protected");
-    private final static FieldAccessor<ClientAuthConfigType, List<ClientAuthContextType>> clientAuthConfigTypeClientAuthContext = new FieldAccessor<ClientAuthConfigType, List<ClientAuthContextType>>(ClientAuthConfigType.class, "clientAuthContext");
+    private final static FieldAccessor<ClientAuthConfigType, Map<String, ClientAuthContextType>> clientAuthConfigTypeClientAuthContext = new FieldAccessor<ClientAuthConfigType, Map<String, ClientAuthContextType>>(ClientAuthConfigType.class, "clientAuthContext");
+    private final static KeyedObjectMapAdapter<ClientAuthContextType> clientAuthContextMapAdapter = new KeyedObjectMapAdapter<ClientAuthContextType>(ClientAuthContextType.class);
 
     public ClientAuthConfigTypeJAXB() {
         super(ClientAuthConfigType.class, null, new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi".intern(), "clientAuthConfigType".intern()), ClientAuthContextTypeJAXB.class);
@@ -66,7 +70,7 @@
         ClientAuthConfigType clientAuthConfigType = new ClientAuthConfigType();
         context.beforeUnmarshal(clientAuthConfigType, lifecycleCallback);
 
-        List<ClientAuthContextType> clientAuthContext = null;
+        List<ClientAuthContextType> clientAuthContextRaw = new ArrayList<ClientAuthContextType>();
 
         // Check xsi:type
         QName xsiType = reader.getXsiType();
@@ -104,20 +108,21 @@
             } else if (("clientAuthContext" == elementReader.getLocalName())&&("http://geronimo.apache.org/xml/ns/geronimo-jaspi" == elementReader.getNamespaceURI())) {
                 // ELEMENT: clientAuthContext
                 ClientAuthContextType clientAuthContextItem = readClientAuthContextType(elementReader, context);
-                if (clientAuthContext == null) {
-                    clientAuthContext = clientAuthConfigTypeClientAuthContext.getObject(reader, context, clientAuthConfigType);
-                    if (clientAuthContext!= null) {
-                        clientAuthContext.clear();
-                    } else {
-                        clientAuthContext = new ArrayList<ClientAuthContextType>();
-                    }
-                }
-                clientAuthContext.add(clientAuthContextItem);
+//                if (clientAuthContextRaw == null) {
+//                    clientAuthContextRaw = clientAuthConfigTypeClientAuthContext.getObject(reader, context, clientAuthConfigType);
+//                    if (clientAuthContextRaw!= null) {
+//                        clientAuthContextRaw.clear();
+//                    } else {
+//                        clientAuthContextRaw = new ArrayList<ClientAuthContextType>();
+//                    }
+//                }
+                clientAuthContextRaw.add(clientAuthContextItem);
             } else {
                 context.unexpectedElement(elementReader, new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "messageLayer"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "appContext"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "authenticationContextID"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "protected"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "clientAuthContext"));
             }
         }
-        if (clientAuthContext!= null) {
+        if (clientAuthContextRaw != null) {
+            Map<String, ClientAuthContextType> clientAuthContext = clientAuthContextMapAdapter.unmarshal(clientAuthContextRaw.toArray(new ClientAuthContextType[clientAuthContextRaw.size()]));
             clientAuthConfigTypeClientAuthContext.setObject(reader, context, clientAuthConfigType, clientAuthContext);
         }
 
@@ -180,7 +185,8 @@
         writer.writeEndElement();
 
         // ELEMENT: clientAuthContext
-        List<ClientAuthContextType> clientAuthContext = clientAuthConfigTypeClientAuthContext.getObject(clientAuthConfigType, context, clientAuthConfigType);
+        Map<String, ClientAuthContextType> clientAuthContextMap = clientAuthConfigTypeClientAuthContext.getObject(clientAuthConfigType, context, clientAuthConfigType);
+        ClientAuthContextType[] clientAuthContext = clientAuthContextMapAdapter.marshal(clientAuthContextMap);
         if (clientAuthContext!= null) {
             for (ClientAuthContextType clientAuthContextItem: clientAuthContext) {
                 writer.writeStartElement(prefix, "clientAuthContext", "http://geronimo.apache.org/xml/ns/geronimo-jaspi");
diff --git a/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ConfigProviderTypeJAXB.java b/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ConfigProviderTypeJAXB.java
index 01eaeb3..00e702c 100644
--- a/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ConfigProviderTypeJAXB.java
+++ b/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ConfigProviderTypeJAXB.java
@@ -17,6 +17,7 @@
 import org.apache.geronimo.components.jaspi.model.ConfigProviderType;
 import org.apache.geronimo.components.jaspi.model.ServerAuthConfigType;
 import org.apache.geronimo.components.jaspi.model.StringMapAdapter;
+import org.apache.geronimo.components.jaspi.model.KeyedObjectMapAdapter;
 
 
 import static sxc.org.apache.geronimo.components.jaspi.model.ClientAuthConfigTypeJAXB.readClientAuthConfigType;
@@ -38,11 +39,13 @@
     private final static FieldAccessor<ConfigProviderType, String> configProviderTypeDescription = new FieldAccessor<ConfigProviderType, String>(ConfigProviderType.class, "description");
     private final static FieldAccessor<ConfigProviderType, String> configProviderTypeClassName = new FieldAccessor<ConfigProviderType, String>(ConfigProviderType.class, "className");
     private final static FieldAccessor<ConfigProviderType, Map<String, String>> configProviderTypeProperties = new FieldAccessor<ConfigProviderType, Map<String, String>>(ConfigProviderType.class, "properties");
-    private final static FieldAccessor<ConfigProviderType, List<ClientAuthConfigType>> configProviderTypeClientAuthConfig = new FieldAccessor<ConfigProviderType, List<ClientAuthConfigType>>(ConfigProviderType.class, "clientAuthConfig");
-    private final static FieldAccessor<ConfigProviderType, List<ServerAuthConfigType>> configProviderTypeServerAuthConfig = new FieldAccessor<ConfigProviderType, List<ServerAuthConfigType>>(ConfigProviderType.class, "serverAuthConfig");
+    private final static FieldAccessor<ConfigProviderType, Map<String, ClientAuthConfigType>> configProviderTypeClientAuthConfig = new FieldAccessor<ConfigProviderType, Map<String, ClientAuthConfigType>>(ConfigProviderType.class, "clientAuthConfig");
+    private final static FieldAccessor<ConfigProviderType, Map<String, ServerAuthConfigType>> configProviderTypeServerAuthConfig = new FieldAccessor<ConfigProviderType, Map<String, ServerAuthConfigType>>(ConfigProviderType.class, "serverAuthConfig");
     private final static FieldAccessor<ConfigProviderType, Boolean> configProviderTypePersistent = new FieldAccessor<ConfigProviderType, Boolean>(ConfigProviderType.class, "persistent");
     private final static FieldAccessor<ConfigProviderType, String> configProviderTypeClassLoaderName = new FieldAccessor<ConfigProviderType, String>(ConfigProviderType.class, "classLoaderName");
     private final static StringMapAdapter stringMapAdapterAdapter = new StringMapAdapter();
+    private final static KeyedObjectMapAdapter<ClientAuthConfigType> clientAuthConfigMapAdapter = new KeyedObjectMapAdapter<ClientAuthConfigType>(ClientAuthConfigType.class);
+    private final static KeyedObjectMapAdapter<ServerAuthConfigType> serverAuthConfigMapAdapter = new KeyedObjectMapAdapter<ServerAuthConfigType>(ServerAuthConfigType.class);
 
     public ConfigProviderTypeJAXB() {
         super(ConfigProviderType.class, null, new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi".intern(), "configProviderType".intern()), ClientAuthConfigTypeJAXB.class, ServerAuthConfigTypeJAXB.class);
@@ -76,8 +79,8 @@
         ConfigProviderType configProviderType = new ConfigProviderType();
         context.beforeUnmarshal(configProviderType, lifecycleCallback);
 
-        List<ClientAuthConfigType> clientAuthConfig = null;
-        List<ServerAuthConfigType> serverAuthConfig = null;
+        List<ClientAuthConfigType> clientAuthConfigRaw = new ArrayList<ClientAuthConfigType>();
+        List<ServerAuthConfigType> serverAuthConfigRaw = new ArrayList<ServerAuthConfigType>();
 
         // Check xsi:type
         QName xsiType = reader.getXsiType();
@@ -128,27 +131,11 @@
             } else if (("clientAuthConfig" == elementReader.getLocalName())&&("http://geronimo.apache.org/xml/ns/geronimo-jaspi" == elementReader.getNamespaceURI())) {
                 // ELEMENT: clientAuthConfig
                 ClientAuthConfigType clientAuthConfigItem = readClientAuthConfigType(elementReader, context);
-                if (clientAuthConfig == null) {
-                    clientAuthConfig = configProviderTypeClientAuthConfig.getObject(reader, context, configProviderType);
-                    if (clientAuthConfig!= null) {
-                        clientAuthConfig.clear();
-                    } else {
-                        clientAuthConfig = new ArrayList<ClientAuthConfigType>();
-                    }
-                }
-                clientAuthConfig.add(clientAuthConfigItem);
+                clientAuthConfigRaw.add(clientAuthConfigItem);
             } else if (("serverAuthConfig" == elementReader.getLocalName())&&("http://geronimo.apache.org/xml/ns/geronimo-jaspi" == elementReader.getNamespaceURI())) {
                 // ELEMENT: serverAuthConfig
                 ServerAuthConfigType serverAuthConfigItem = readServerAuthConfigType(elementReader, context);
-                if (serverAuthConfig == null) {
-                    serverAuthConfig = configProviderTypeServerAuthConfig.getObject(reader, context, configProviderType);
-                    if (serverAuthConfig!= null) {
-                        serverAuthConfig.clear();
-                    } else {
-                        serverAuthConfig = new ArrayList<ServerAuthConfigType>();
-                    }
-                }
-                serverAuthConfig.add(serverAuthConfigItem);
+                serverAuthConfigRaw.add(serverAuthConfigItem);
             } else if (("persistent" == elementReader.getLocalName())&&("http://geronimo.apache.org/xml/ns/geronimo-jaspi" == elementReader.getNamespaceURI())) {
                 // ELEMENT: persistent
                 Boolean persistent = ("1".equals(elementReader.getElementAsString())||"true".equals(elementReader.getElementAsString()));
@@ -161,10 +148,12 @@
                 context.unexpectedElement(elementReader, new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "messageLayer"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "appContext"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "description"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "className"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "properties"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "clientAuthConfig"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "serverAuthConfig"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "persistent"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "classLoaderName"));
             }
         }
-        if (clientAuthConfig!= null) {
+        if (clientAuthConfigRaw!= null) {
+            Map<String, ClientAuthConfigType> clientAuthConfig = clientAuthConfigMapAdapter.unmarshal(clientAuthConfigRaw.toArray(new ClientAuthConfigType[clientAuthConfigRaw.size()]));
             configProviderTypeClientAuthConfig.setObject(reader, context, configProviderType, clientAuthConfig);
         }
-        if (serverAuthConfig!= null) {
+        if (serverAuthConfigRaw!= null) {
+            Map<String, ServerAuthConfigType> serverAuthConfig = serverAuthConfigMapAdapter.unmarshal(serverAuthConfigRaw.toArray(new ServerAuthConfigType[serverAuthConfigRaw.size()]));
             configProviderTypeServerAuthConfig.setObject(reader, context, configProviderType, serverAuthConfig);
         }
 
@@ -243,7 +232,8 @@
         }
 
         // ELEMENT: clientAuthConfig
-        List<ClientAuthConfigType> clientAuthConfig = configProviderTypeClientAuthConfig.getObject(configProviderType, context, configProviderType);
+        Map<String, ClientAuthConfigType> clientAuthConfigMap = configProviderTypeClientAuthConfig.getObject(configProviderType, context, configProviderType);
+        ClientAuthConfigType[] clientAuthConfig = clientAuthConfigMapAdapter.marshal(clientAuthConfigMap);
         if (clientAuthConfig!= null) {
             for (ClientAuthConfigType clientAuthConfigItem: clientAuthConfig) {
                 writer.writeStartElement(prefix, "clientAuthConfig", "http://geronimo.apache.org/xml/ns/geronimo-jaspi");
@@ -257,7 +247,8 @@
         }
 
         // ELEMENT: serverAuthConfig
-        List<ServerAuthConfigType> serverAuthConfig = configProviderTypeServerAuthConfig.getObject(configProviderType, context, configProviderType);
+        Map<String,ServerAuthConfigType> serverAuthConfigMap = configProviderTypeServerAuthConfig.getObject(configProviderType, context, configProviderType);
+        ServerAuthConfigType[] serverAuthConfig = serverAuthConfigMapAdapter.marshal(serverAuthConfigMap);
         if (serverAuthConfig!= null) {
             for (ServerAuthConfigType serverAuthConfigItem: serverAuthConfig) {
                 writer.writeStartElement(prefix, "serverAuthConfig", "http://geronimo.apache.org/xml/ns/geronimo-jaspi");
diff --git a/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/JaspiTypeJAXB.java b/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/JaspiTypeJAXB.java
index f4a9984..4ac483a 100644
--- a/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/JaspiTypeJAXB.java
+++ b/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/JaspiTypeJAXB.java
@@ -14,7 +14,7 @@
 import com.envoisolutions.sxc.util.Attribute;
 import com.envoisolutions.sxc.util.XoXMLStreamReader;
 import com.envoisolutions.sxc.util.XoXMLStreamWriter;
-import org.apache.geronimo.components.jaspi.model.ConfigProviderMapAdapter;
+import org.apache.geronimo.components.jaspi.model.KeyedObjectMapAdapter;
 import org.apache.geronimo.components.jaspi.model.ConfigProviderType;
 import org.apache.geronimo.components.jaspi.model.JaspiType;
 import static sxc.org.apache.geronimo.components.jaspi.model.ConfigProviderTypeJAXB.readConfigProviderType;
@@ -30,7 +30,7 @@
     public final static JaspiTypeJAXB INSTANCE = new JaspiTypeJAXB();
     private final static LifecycleCallback lifecycleCallback = new LifecycleCallback(JaspiType.class);
     private final static FieldAccessor<JaspiType, Map<String, ConfigProviderType>> jaspiTypeConfigProvider = new FieldAccessor<JaspiType, Map<String, ConfigProviderType>>(JaspiType.class, "configProvider");
-    private final static ConfigProviderMapAdapter configProviderMapAdapterAdapter = new ConfigProviderMapAdapter();
+    private final static KeyedObjectMapAdapter<ConfigProviderType> configProviderMapAdapterAdapter = new KeyedObjectMapAdapter<ConfigProviderType>(ConfigProviderType.class);
 
     public JaspiTypeJAXB() {
         super(JaspiType.class, null, new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi".intern(), "jaspiType".intern()));
@@ -102,7 +102,7 @@
             configProvider = configProviderMapAdapterAdapter.unmarshal(configProviderArray);
             jaspiTypeConfigProvider.setObject(reader, context, jaspiType, configProvider);
         } catch (Exception e) {
-//            context.xmlAdapterError(null, ConfigProviderMapAdapter.class, Map.class, Map.class, e);
+//            context.xmlAdapterError(null, KeyedObjectMapAdapter.class, Map.class, Map.class, e);
             throw e;
         }
 
@@ -138,7 +138,7 @@
         try {
             configProvider = configProviderMapAdapterAdapter.marshal(configProviderRaw);
         } catch (Exception e) {
-            context.xmlAdapterError(jaspiType, "configProvider", ConfigProviderMapAdapter.class, Map.class, Map.class, e);
+            context.xmlAdapterError(jaspiType, "configProvider", KeyedObjectMapAdapter.class, Map.class, Map.class, e);
         }
         if (configProvider!= null) {
             for (ConfigProviderType configProviderItem: configProvider) {
diff --git a/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ServerAuthConfigTypeJAXB.java b/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ServerAuthConfigTypeJAXB.java
index bb14765..428f2b7 100644
--- a/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ServerAuthConfigTypeJAXB.java
+++ b/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ServerAuthConfigTypeJAXB.java
@@ -3,6 +3,8 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+
 import javax.xml.XMLConstants;
 import javax.xml.namespace.QName;
 import com.envoisolutions.sxc.jaxb.FieldAccessor;
@@ -14,6 +16,7 @@
 import com.envoisolutions.sxc.util.XoXMLStreamWriter;
 import org.apache.geronimo.components.jaspi.model.ServerAuthConfigType;
 import org.apache.geronimo.components.jaspi.model.ServerAuthContextType;
+import org.apache.geronimo.components.jaspi.model.KeyedObjectMapAdapter;
 
 
 import static sxc.org.apache.geronimo.components.jaspi.model.ServerAuthContextTypeJAXB.readServerAuthContextType;
@@ -32,7 +35,8 @@
     private final static FieldAccessor<ServerAuthConfigType, String> serverAuthConfigTypeAppContext = new FieldAccessor<ServerAuthConfigType, String>(ServerAuthConfigType.class, "appContext");
     private final static FieldAccessor<ServerAuthConfigType, String> serverAuthConfigTypeAuthenticationContextID = new FieldAccessor<ServerAuthConfigType, String>(ServerAuthConfigType.class, "authenticationContextID");
     private final static FieldAccessor<ServerAuthConfigType, Boolean> serverAuthConfigType_protected = new FieldAccessor<ServerAuthConfigType, Boolean>(ServerAuthConfigType.class, "_protected");
-    private final static FieldAccessor<ServerAuthConfigType, List<ServerAuthContextType>> serverAuthConfigTypeServerAuthContext = new FieldAccessor<ServerAuthConfigType, List<ServerAuthContextType>>(ServerAuthConfigType.class, "serverAuthContext");
+    private final static FieldAccessor<ServerAuthConfigType, Map<String, ServerAuthContextType>> serverAuthConfigTypeServerAuthContext = new FieldAccessor<ServerAuthConfigType, Map<String, ServerAuthContextType>>(ServerAuthConfigType.class, "serverAuthContext");
+    private final static KeyedObjectMapAdapter<ServerAuthContextType> serverAuthContextMapAdapter = new KeyedObjectMapAdapter<ServerAuthContextType>(ServerAuthContextType.class);
 
     public ServerAuthConfigTypeJAXB() {
         super(ServerAuthConfigType.class, null, new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi".intern(), "serverAuthConfigType".intern()), ServerAuthContextTypeJAXB.class);
@@ -66,7 +70,7 @@
         ServerAuthConfigType serverAuthConfigType = new ServerAuthConfigType();
         context.beforeUnmarshal(serverAuthConfigType, lifecycleCallback);
 
-        List<ServerAuthContextType> serverAuthContext = null;
+        List<ServerAuthContextType> serverAuthContextRaw = new ArrayList<ServerAuthContextType>();
 
         // Check xsi:type
         QName xsiType = reader.getXsiType();
@@ -104,20 +108,21 @@
             } else if (("serverAuthContext" == elementReader.getLocalName())&&("http://geronimo.apache.org/xml/ns/geronimo-jaspi" == elementReader.getNamespaceURI())) {
                 // ELEMENT: serverAuthContext
                 ServerAuthContextType serverAuthContextItem = readServerAuthContextType(elementReader, context);
-                if (serverAuthContext == null) {
-                    serverAuthContext = serverAuthConfigTypeServerAuthContext.getObject(reader, context, serverAuthConfigType);
-                    if (serverAuthContext!= null) {
-                        serverAuthContext.clear();
-                    } else {
-                        serverAuthContext = new ArrayList<ServerAuthContextType>();
-                    }
-                }
-                serverAuthContext.add(serverAuthContextItem);
+//                if (serverAuthContextRaw == null) {
+//                    serverAuthContextRaw = serverAuthConfigTypeServerAuthContext.getObject(reader, context, serverAuthConfigType);
+//                    if (serverAuthContextRaw != null) {
+//                        serverAuthContextRaw.clear();
+//                    } else {
+//                        serverAuthContextRaw = new ArrayList<ServerAuthContextType>();
+//                    }
+//                }
+                serverAuthContextRaw.add(serverAuthContextItem);
             } else {
                 context.unexpectedElement(elementReader, new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "messageLayer"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "appContext"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "authenticationContextID"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "protected"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "serverAuthContext"));
             }
         }
-        if (serverAuthContext!= null) {
+        if (serverAuthContextRaw != null) {
+            Map<String, ServerAuthContextType> serverAuthContext = serverAuthContextMapAdapter.unmarshal(serverAuthContextRaw.toArray(new ServerAuthContextType[serverAuthContextRaw.size()]));
             serverAuthConfigTypeServerAuthContext.setObject(reader, context, serverAuthConfigType, serverAuthContext);
         }
 
@@ -180,7 +185,8 @@
         writer.writeEndElement();
 
         // ELEMENT: serverAuthContext
-        List<ServerAuthContextType> serverAuthContext = serverAuthConfigTypeServerAuthContext.getObject(serverAuthConfigType, context, serverAuthConfigType);
+        Map<String, ServerAuthContextType> serverAuthContextMap = serverAuthConfigTypeServerAuthContext.getObject(serverAuthConfigType, context, serverAuthConfigType);
+        ServerAuthContextType[] serverAuthContext = serverAuthContextMapAdapter.marshal(serverAuthContextMap);
         if (serverAuthContext!= null) {
             for (ServerAuthContextType serverAuthContextItem: serverAuthContext) {
                 writer.writeStartElement(prefix, "serverAuthContext", "http://geronimo.apache.org/xml/ns/geronimo-jaspi");
diff --git a/geronimo-jaspi/src/main/xsd/geronimo-jaspi.xsd b/geronimo-jaspi/src/main/xsd/geronimo-jaspi.xsd
index 4b550f0..8f6b05a 100644
--- a/geronimo-jaspi/src/main/xsd/geronimo-jaspi.xsd
+++ b/geronimo-jaspi/src/main/xsd/geronimo-jaspi.xsd
@@ -286,7 +286,7 @@
                     </xs:documentation>
                 </xs:annotation>
             </xs:element>
-            <xs:element name="authenticationContextID" type="xs:string">
+            <xs:element name="authenticationContextID" type="xs:string" minOccurs="0">
                 <xs:annotation>
                     <xs:documentation>
                         the constant value to be returned from getAuthContextID(MessageInfo messageInfo)
@@ -313,10 +313,17 @@
                     </xs:documentation>
                 </xs:annotation>
             </xs:element>
-            <xs:element name="requestPolicy" type="jaspi:messagePolicyType">
+            <xs:element name="classLoaderName" type="xs:string" minOccurs="0">
+                <xs:annotation>
+                    <xs:documentation>
+                        name of classloader to load any needed classes (e.g. custom config providers, modules, policy stuff)
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="requestPolicy" type="jaspi:messagePolicyType" minOccurs="0">
 
             </xs:element>
-            <xs:element name="responsePolicy" type="jaspi:messagePolicyType">
+            <xs:element name="responsePolicy" type="jaspi:messagePolicyType" minOccurs="0">
 
             </xs:element>
             <xs:element name="options"
diff --git a/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/AuthConfigFactoryImplTest.java b/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/AuthConfigFactoryImplTest.java
index f22a189..1b3475d 100644
--- a/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/AuthConfigFactoryImplTest.java
+++ b/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/AuthConfigFactoryImplTest.java
@@ -23,6 +23,7 @@
 import javax.security.auth.message.config.AuthConfigFactory;

 import javax.security.auth.message.config.RegistrationListener;

 import javax.security.auth.message.config.AuthConfigFactory.RegistrationContext;

+import javax.security.auth.callback.CallbackHandler;

 

 import junit.framework.TestCase;

 

@@ -35,6 +36,8 @@
     protected void setUp() throws Exception {

         URL url = getClass().getClassLoader().getResource("test-jaspi.xml");

         AuthConfigFactoryImpl.staticConfigFile = new File(url.getPath());

+        CallbackHandler callbackHandler = null;

+        AuthConfigFactoryImpl.staticCallbackHandler = callbackHandler;

         AuthConfigFactory.setFactory(null);

     }

     

diff --git a/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/model/JaxbTest.java b/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/model/JaxbTest.java
index 52107b8..2946920 100644
--- a/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/model/JaxbTest.java
+++ b/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/model/JaxbTest.java
@@ -34,6 +34,11 @@
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamException;
+import javax.security.auth.message.config.AuthConfigProvider;
+import javax.security.auth.message.config.ClientAuthConfig;
+import javax.security.auth.message.config.ClientAuthContext;
+import javax.security.auth.message.config.ServerAuthConfig;
+import javax.security.auth.message.config.ServerAuthContext;
 
 import org.testng.annotations.Test;
 import org.xml.sax.SAXException;
@@ -53,13 +58,40 @@
         JaspiType jaspi1 = loadJaspi(file);
         if (jaspi1.getConfigProvider().size() != count) throw new Exception("expected " + count + " configprovider, not this: " + jaspi1.getConfigProvider());
         URL url = getClass().getClassLoader().getResource("test-jaspi.xml");
-        File newFile = new File(new File(url.getPath()).getParentFile(), "test-jaspi-2.xml");
+        File newFile = new File(new File(url.getPath()).getParentFile(), "test-jaspi-write.xml");
         Writer writer = new FileWriter(newFile);
         JaspiXmlUtil.writeJaspi(jaspi1, writer);
         JaspiType jaspi2 = JaspiXmlUtil.loadJaspi(new FileReader(newFile));
         if (jaspi2.getConfigProvider().size() != count) throw new Exception("expected " + count + " configprovider, not this: " + jaspi2.getConfigProvider());
     }
 
+    @Test
+    public void testLoad2() throws Exception {
+        String file = "test-jaspi-2.xml";
+        JaspiType jaspi1 = loadJaspi(file);
+        if (jaspi1.getConfigProvider().size() != count) throw new Exception("expected " + count + " configprovider, not this: " + jaspi1.getConfigProvider());
+        URL url = getClass().getClassLoader().getResource("test-jaspi.xml");
+        File newFile = new File(new File(url.getPath()).getParentFile(), "test-jaspi-2-write.xml");
+        Writer writer = new FileWriter(newFile);
+        JaspiXmlUtil.writeJaspi(jaspi1, writer);
+        JaspiType jaspi2 = JaspiXmlUtil.loadJaspi(new FileReader(newFile));
+        if (jaspi2.getConfigProvider().size() != count) throw new Exception("expected " + count + " configprovider, not this: " + jaspi2.getConfigProvider());
+
+        AuthConfigProvider configProvider = jaspi1.getConfigProvider().get(ConfigProviderType.getRegistrationKey("Http", "test-app1")).getProvider();
+        ClientAuthConfig clientAuthConfig = configProvider.getClientAuthConfig("Http", "test-app1", null);
+        String authContextID = clientAuthConfig.getAuthContextID(null);
+        ClientAuthContext clientAuthContext = clientAuthConfig.getAuthContext(authContextID, null, null);
+        clientAuthContext.secureRequest(null, null);
+
+        ServerAuthConfig serverAuthConfig = configProvider.getServerAuthConfig("Http", "test-app1", null);
+         authContextID = serverAuthConfig.getAuthContextID(null);
+        ServerAuthContext serverAuthContext = serverAuthConfig.getAuthContext(authContextID, null, null);
+        serverAuthContext.secureResponse(null, null);
+
+
+
+    }
+
     private JaspiType loadJaspi(String file) throws ParserConfigurationException, IOException, SAXException, JAXBException, XMLStreamException {
         InputStream in = getClass().getClassLoader().getResourceAsStream(file);
         Reader reader = new InputStreamReader(in);
diff --git a/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/providers/DummyClientAuthModule.java b/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/providers/DummyClientAuthModule.java
new file mode 100644
index 0000000..a4f1c88
--- /dev/null
+++ b/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/providers/DummyClientAuthModule.java
@@ -0,0 +1,54 @@
+/*
+ * 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.geronimo.components.jaspi.providers;
+
+import java.util.Map;
+
+import javax.security.auth.message.module.ClientAuthModule;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.Subject;
+
+/**
+ * @version $Rev:$ $Date:$
+ */
+public class DummyClientAuthModule implements ClientAuthModule {
+    public Class[] getSupportedMessageTypes() {
+        return new Class[0];
+    }
+
+    public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler, Map options) throws AuthException {
+    }
+
+    public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+    }
+
+    public AuthStatus secureRequest(MessageInfo messageInfo, Subject clientSubject) throws AuthException {
+        return AuthStatus.SUCCESS;
+    }
+
+    public AuthStatus validateResponse(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+        return AuthStatus.SUCCESS;
+    }
+}
diff --git a/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/providers/DummyServerAuthModule.java b/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/providers/DummyServerAuthModule.java
new file mode 100644
index 0000000..13de475
--- /dev/null
+++ b/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/providers/DummyServerAuthModule.java
@@ -0,0 +1,54 @@
+/*
+ * 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.geronimo.components.jaspi.providers;
+
+import java.util.Map;
+
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.Subject;
+
+/**
+ * @version $Rev:$ $Date:$
+ */
+public class DummyServerAuthModule implements ServerAuthModule {
+    public Class[] getSupportedMessageTypes() {
+        return new Class[0];
+    }
+
+    public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler, Map options) throws AuthException {
+    }
+
+    public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+    }
+
+    public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+        return AuthStatus.SEND_SUCCESS;
+    }
+
+    public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+        return AuthStatus.SUCCESS;
+    }
+}
diff --git a/geronimo-jaspi/src/test/resources/test-jaspi-2.xml b/geronimo-jaspi/src/test/resources/test-jaspi-2.xml
new file mode 100644
index 0000000..52b6908
--- /dev/null
+++ b/geronimo-jaspi/src/test/resources/test-jaspi-2.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+
+<jaspi xmlns="http://geronimo.apache.org/xml/ns/geronimo-jaspi">
+
+    <configProvider>
+        <messageLayer>Http</messageLayer>
+        <appContext>test-app1</appContext>
+        <description>description</description>
+        <clientAuthConfig>
+            <authenticationContextID>authenticationContextID1</authenticationContextID>
+            <protected>true</protected>
+            <clientAuthContext>
+                <clientAuthModule>
+                    <className>org.apache.geronimo.components.jaspi.providers.DummyClientAuthModule</className>
+                </clientAuthModule>
+            </clientAuthContext>
+        </clientAuthConfig>
+        <serverAuthConfig>
+            <authenticationContextID>authenticationContextID2</authenticationContextID>
+            <protected>true</protected>
+            <serverAuthContext>
+                <serverAuthModule>
+                    <className>org.apache.geronimo.components.jaspi.providers.DummyServerAuthModule</className>
+                </serverAuthModule>
+            </serverAuthContext>
+        </serverAuthConfig>
+        <persistent>true</persistent>
+    </configProvider>
+
+    <configProvider>
+        <messageLayer>Http</messageLayer>
+        <appContext>test-app2</appContext>
+        <description>description2</description>
+        <className>org.apache.geronimo.components.jaspi.providers.DummyProvider</className>
+        <properties>foo=bar</properties>
+        <persistent>true</persistent>
+    </configProvider>
+
+</jaspi>
\ No newline at end of file