a bit more work on the model

git-svn-id: https://svn.apache.org/repos/asf/geronimo/components/jaspi/trunk@677372 13f79535-47bb-0310-9956-ffa450edef68
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 0b813de..ad4a8cb 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
@@ -9,10 +9,14 @@
 package org.apache.geronimo.components.jaspi.model;
 
 import java.io.Serializable;
+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.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 
 
 /**
@@ -44,7 +48,7 @@
     "responsePolicy",
     "options"
 })
-public class AuthModuleType
+public class AuthModuleType<T>
     implements Serializable
 {
 
@@ -55,7 +59,10 @@
     protected MessagePolicyType requestPolicy;
     @XmlElement(required = true)
     protected MessagePolicyType responsePolicy;
-    protected String options;
+    @XmlJavaTypeAdapter(StringMapAdapter.class)
+    protected Map<String, String> options;
+    @XmlTransient
+    private T authModule;
 
     /**
      * Gets the value of the className property.
@@ -134,10 +141,10 @@
      * 
      * @return
      *     possible object is
-     *     {@link String }
+     *     {@link Map<String, String> }
      *     
      */
-    public String getOptions() {
+    public Map<String, String> getOptions() {
         return options;
     }
 
@@ -146,11 +153,18 @@
      * 
      * @param value
      *     allowed object is
-     *     {@link String }
+     *     {@link Map<String, String> }
      *     
      */
-    public void setOptions(String value) {
+    public void setOptions(Map<String, String> value) {
         this.options = value;
     }
 
+    public void createAuthModule(ClassLoader classLoader) {
+        throw new RuntimeException("NYI");
+    }
+
+    public T getAuthModule() {
+        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 cc492e5..f693f47 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
@@ -11,10 +11,17 @@
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
+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.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;
 
 
 /**
@@ -29,7 +36,7 @@
  *       &lt;sequence>
  *         &lt;element name="messageLayer" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
  *         &lt;element name="appContext" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- *         &lt;element name="authenticationContextID" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         &lt;element name="authenticationContextID" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
  *         &lt;element name="protected" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
  *         &lt;element name="clientAuthContext" type="{http://geronimo.apache.org/xml/ns/geronimo-jaspi}clientAuthContextType" maxOccurs="unbounded" minOccurs="0"/>
  *       &lt;/sequence>
@@ -49,13 +56,12 @@
     "clientAuthContext"
 })
 public class ClientAuthConfigType
-    implements Serializable
+    implements ClientAuthConfig, Serializable
 {
 
     private final static long serialVersionUID = 12343L;
     protected String messageLayer;
     protected String appContext;
-    @XmlElement(required = true)
     protected String authenticationContextID;
     @XmlElement(name = "protected")
     protected boolean _protected;
@@ -97,6 +103,19 @@
         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.
      * 
@@ -141,6 +160,9 @@
         return _protected;
     }
 
+    public void refresh() throws AuthException, SecurityException {
+    }
+
     /**
      * Sets the value of the protected property.
      * 
@@ -178,4 +200,7 @@
         return this.clientAuthContext;
     }
 
+    public ClientAuthContext getAuthContext(String authContextID, Subject clientSubject, Map properties) throws AuthException {
+        return null;
+    }
 }
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 561762a..645c251 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
@@ -15,6 +15,12 @@
 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;
 
 
 /**
@@ -47,7 +53,7 @@
     "clientAuthModule"
 })
 public class ClientAuthContextType
-    implements Serializable
+    implements ClientAuthContext, Serializable
 {
 
     private final static long serialVersionUID = 12343L;
@@ -55,7 +61,7 @@
     protected String appContext;
     @XmlElement(required = true)
     protected String authenticationContextID;
-    protected List<AuthModuleType> clientAuthModule;
+    protected List<AuthModuleType<ClientAuthModule>> clientAuthModule;
 
     /**
      * Gets the value of the messageLayer property.
@@ -117,6 +123,10 @@
         return authenticationContextID;
     }
 
+    public String getAuthenticationContextID(MessageInfo messageInfo) {
+        return authenticationContextID;
+    }
+
     /**
      * Sets the value of the authenticationContextID property.
      * 
@@ -149,13 +159,54 @@
      * Objects of the following type(s) are allowed in the list
      * {@link AuthModuleType }
      * 
-     * 
+     *
+     * @return list of client auth module wrappers
      */
-    public List<AuthModuleType> getClientAuthModule() {
+    public List<AuthModuleType<ClientAuthModule>> getClientAuthModule() {
         if (clientAuthModule == null) {
-            clientAuthModule = new ArrayList<AuthModuleType>();
+            clientAuthModule = new ArrayList<AuthModuleType<ClientAuthModule>>();
         }
         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 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/ServerAuthConfigType.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ServerAuthConfigType.java
index 494d7cb..372755c 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
@@ -11,10 +11,17 @@
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
+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.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;
 
 
 /**
@@ -49,13 +56,12 @@
     "serverAuthContext"
 })
 public class ServerAuthConfigType
-    implements Serializable
+    implements ServerAuthConfig, Serializable
 {
 
     private final static long serialVersionUID = 12343L;
     protected String messageLayer;
     protected String appContext;
-    @XmlElement(required = true)
     protected String authenticationContextID;
     @XmlElement(name = "protected")
     protected boolean _protected;
@@ -97,6 +103,19 @@
         return appContext;
     }
 
+    public String getAuthContextID(MessageInfo messageInfo) throws IllegalArgumentException {
+        if (authenticationContextID != null) {
+            return authenticationContextID;
+        }
+        for (ServerAuthContextType serverAuthContextType: serverAuthContext) {
+            String authContextID = serverAuthContextType.getAuthenticationContextID(messageInfo);
+            if (authContextID != null) {
+                return authContextID;
+            }
+        }
+        return null;
+    }
+
     /**
      * Sets the value of the appContext property.
      * 
@@ -141,6 +160,9 @@
         return _protected;
     }
 
+    public void refresh() throws AuthException, SecurityException {
+    }
+
     /**
      * Sets the value of the protected property.
      * 
@@ -178,4 +200,7 @@
         return this.serverAuthContext;
     }
 
+    public ServerAuthContext getAuthContext(String authContextID, Subject serviceSubject, Map properties) throws AuthException {
+        return null;
+    }
 }
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 3393e04..2e5c000 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
@@ -11,6 +11,14 @@
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
+
+import javax.security.auth.Subject;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.security.auth.message.module.ClientAuthModule;
+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;
@@ -19,9 +27,9 @@
 
 /**
  * <p>Java class for serverAuthContextType complex type.
- * 
+ * <p/>
  * <p>The following schema fragment specifies the expected content contained within this class.
- * 
+ * <p/>
  * <pre>
  * &lt;complexType name="serverAuthContextType">
  *   &lt;complexContent>
@@ -36,34 +44,29 @@
  *   &lt;/complexContent>
  * &lt;/complexType>
  * </pre>
- * 
- * 
  */
 @XmlAccessorType(XmlAccessType.FIELD)
 @XmlType(name = "serverAuthContextType", propOrder = {
-    "messageLayer",
-    "appContext",
-    "authenticationContextID",
-    "serverAuthModule"
-})
+        "messageLayer",
+        "appContext",
+        "authenticationContextID",
+        "serverAuthModule"
+        })
 public class ServerAuthContextType
-    implements Serializable
-{
+        implements ServerAuthContext, Serializable {
 
     private final static long serialVersionUID = 12343L;
     protected String messageLayer;
     protected String appContext;
     @XmlElement(required = true)
     protected String authenticationContextID;
-    protected List<AuthModuleType> serverAuthModule;
+    protected List<AuthModuleType<ServerAuthModule>> serverAuthModule;
 
     /**
      * Gets the value of the messageLayer property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
+     *
+     * @return possible object is
+     *         {@link String }
      */
     public String getMessageLayer() {
         return messageLayer;
@@ -71,11 +74,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;
@@ -83,11 +84,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;
@@ -95,11 +94,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;
@@ -107,23 +104,23 @@
 
     /**
      * Gets the value of the authenticationContextID property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
+     *
+     * @return possible object is
+     *         {@link String }
      */
     public String getAuthenticationContextID() {
         return authenticationContextID;
     }
 
+    public String getAuthenticationContextID(MessageInfo messageInfo) {
+        return authenticationContextID;
+    }
+
     /**
      * 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;
@@ -131,31 +128,69 @@
 
     /**
      * Gets the value of the serverAuthModule 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 serverAuthModule property.
-     * 
-     * <p>
+     * <p/>
+     * <p/>
      * For example, to add a new item, do as follows:
      * <pre>
      *    getServerAuthModule().add(newItem);
      * </pre>
-     * 
-     * 
-     * <p>
+     * <p/>
+     * <p/>
+     * <p/>
      * Objects of the following type(s) are allowed in the list
      * {@link AuthModuleType }
-     * 
-     * 
      */
-    public List<AuthModuleType> getServerAuthModule() {
+    public List<AuthModuleType<ServerAuthModule>> getServerAuthModule() {
         if (serverAuthModule == null) {
-            serverAuthModule = new ArrayList<AuthModuleType>();
+            serverAuthModule = new ArrayList<AuthModuleType<ServerAuthModule>>();
         }
         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 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);
+        }
+        return AuthStatus.SEND_SUCCESS;
+    }
+
+    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;
+    }
 }
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 119e7fc..d86cd2e 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
@@ -1,8 +1,12 @@
 
 package sxc.org.apache.geronimo.components.jaspi.model;
 
+import java.util.Map;
 import javax.xml.XMLConstants;
 import javax.xml.namespace.QName;
+import javax.security.auth.message.module.ClientAuthModule;
+import javax.security.auth.message.module.ServerAuthModule;
+
 import com.envoisolutions.sxc.jaxb.FieldAccessor;
 import com.envoisolutions.sxc.jaxb.JAXBObject;
 import com.envoisolutions.sxc.jaxb.LifecycleCallback;
@@ -12,6 +16,7 @@
 import com.envoisolutions.sxc.util.XoXMLStreamWriter;
 import org.apache.geronimo.components.jaspi.model.AuthModuleType;
 import org.apache.geronimo.components.jaspi.model.MessagePolicyType;
+import org.apache.geronimo.components.jaspi.model.StringMapAdapter;
 
 
 import static sxc.org.apache.geronimo.components.jaspi.model.MessagePolicyTypeJAXB.readMessagePolicyType;
@@ -20,37 +25,50 @@
 @SuppressWarnings({
     "StringEquality"
 })
-public class AuthModuleTypeJAXB
+public class AuthModuleTypeJAXB<T>
     extends JAXBObject<AuthModuleType>
 {
 
-    public final static AuthModuleTypeJAXB INSTANCE = new AuthModuleTypeJAXB();
+    public final static AuthModuleTypeJAXB<ClientAuthModule> CLIENT_INSTANCE = new AuthModuleTypeJAXB<ClientAuthModule>();
+    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, 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, String> authModuleTypeOptions = new FieldAccessor<AuthModuleType, String>(AuthModuleType.class, "options");
+    private final static FieldAccessor<AuthModuleType, Map<String, String>> authModuleTypeOptions = new FieldAccessor<AuthModuleType, Map<String, String>>(AuthModuleType.class, "options");
+    private final static StringMapAdapter stringMapAdapterAdapter = new StringMapAdapter();
 
     public AuthModuleTypeJAXB() {
         super(AuthModuleType.class, null, new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi".intern(), "authModuleType".intern()), MessagePolicyTypeJAXB.class);
     }
 
-    public static AuthModuleType readAuthModuleType(XoXMLStreamReader reader, RuntimeContext context)
+    public static AuthModuleType<ClientAuthModule> readClientAuthModuleType(XoXMLStreamReader reader, RuntimeContext context)
         throws Exception
     {
-        return INSTANCE.read(reader, context);
+        return CLIENT_INSTANCE.read(reader, context);
     }
 
-    public static void writeAuthModuleType(XoXMLStreamWriter writer, AuthModuleType authModuleType, RuntimeContext context)
+    public static void writeClientAuthModuleType(XoXMLStreamWriter writer, AuthModuleType authModuleType, RuntimeContext context)
         throws Exception
     {
-        INSTANCE.write(writer, authModuleType, context);
+        CLIENT_INSTANCE.write(writer, authModuleType, context);
     }
 
-    public final AuthModuleType read(XoXMLStreamReader reader, RuntimeContext context)
+    public static AuthModuleType<ServerAuthModule> readServerAuthModuleType(XoXMLStreamReader reader, RuntimeContext context)
         throws Exception
     {
+        return SERVER_INSTANCE.read(reader, context);
+    }
 
+    public static void writeServerAuthModuleType(XoXMLStreamWriter writer, AuthModuleType authModuleType, RuntimeContext context)
+        throws Exception
+    {
+        SERVER_INSTANCE.write(writer, authModuleType, context);
+    }
+
+    public final AuthModuleType<T> read(XoXMLStreamReader reader, RuntimeContext context)
+        throws Exception
+    {
         // Check for xsi:nil
         if (reader.isXsiNil()) {
             return null;
@@ -60,7 +78,7 @@
             context = new RuntimeContext();
         }
 
-        AuthModuleType authModuleType = new AuthModuleType();
+        AuthModuleType<T> authModuleType = new AuthModuleType<T>();
         context.beforeUnmarshal(authModuleType, lifecycleCallback);
 
 
@@ -95,7 +113,16 @@
                 authModuleTypeResponsePolicy.setObject(reader, context, authModuleType, responsePolicy);
             } else if (("options" == elementReader.getLocalName())&&("http://geronimo.apache.org/xml/ns/geronimo-jaspi" == elementReader.getNamespaceURI())) {
                 // ELEMENT: options
-                String options = elementReader.getElementAsString();
+                String optionsRaw = elementReader.getElementAsString();
+
+                Map<String, String> options;
+                try {
+                    options = stringMapAdapterAdapter.unmarshal(optionsRaw);
+                } catch (Exception e) {
+                    context.xmlAdapterError(elementReader, StringMapAdapter.class, Map.class, Map.class, e);
+                    continue;
+                }
+
                 authModuleTypeOptions.setObject(reader, context, authModuleType, options);
             } else {
                 context.unexpectedElement(elementReader, new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "className"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "requestPolicy"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "responsePolicy"), new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "options"));
@@ -159,7 +186,13 @@
         }
 
         // ELEMENT: options
-        String options = authModuleTypeOptions.getObject(authModuleType, context, authModuleType);
+        Map<String, String> optionsRaw = authModuleTypeOptions.getObject(authModuleType, context, authModuleType);
+        String options = null;
+        try {
+            options = stringMapAdapterAdapter.marshal(optionsRaw);
+        } catch (Exception e) {
+            context.xmlAdapterError(authModuleType, "options", StringMapAdapter.class, Map.class, Map.class, e);
+        }
         if (options!= null) {
             writer.writeStartElement(prefix, "options", "http://geronimo.apache.org/xml/ns/geronimo-jaspi");
             writer.writeCharacters(options);
diff --git a/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ClientAuthContextTypeJAXB.java b/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ClientAuthContextTypeJAXB.java
index 4e14901..2209e17 100644
--- a/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ClientAuthContextTypeJAXB.java
+++ b/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ClientAuthContextTypeJAXB.java
@@ -16,8 +16,8 @@
 import org.apache.geronimo.components.jaspi.model.ClientAuthContextType;
 
 
-import static sxc.org.apache.geronimo.components.jaspi.model.AuthModuleTypeJAXB.readAuthModuleType;
-import static sxc.org.apache.geronimo.components.jaspi.model.AuthModuleTypeJAXB.writeAuthModuleType;
+import static sxc.org.apache.geronimo.components.jaspi.model.AuthModuleTypeJAXB.readClientAuthModuleType;
+import static sxc.org.apache.geronimo.components.jaspi.model.AuthModuleTypeJAXB.writeClientAuthModuleType;
 
 @SuppressWarnings({
     "StringEquality"
@@ -98,7 +98,7 @@
                 clientAuthContextTypeAuthenticationContextID.setObject(reader, context, clientAuthContextType, authenticationContextID);
             } else if (("clientAuthModule" == elementReader.getLocalName())&&("http://geronimo.apache.org/xml/ns/geronimo-jaspi" == elementReader.getNamespaceURI())) {
                 // ELEMENT: clientAuthModule
-                AuthModuleType clientAuthModuleItem = readAuthModuleType(elementReader, context);
+                AuthModuleType clientAuthModuleItem = readClientAuthModuleType(elementReader, context);
                 if (clientAuthModule == null) {
                     clientAuthModule = clientAuthContextTypeClientAuthModule.getObject(reader, context, clientAuthContextType);
                     if (clientAuthModule!= null) {
@@ -174,7 +174,7 @@
             for (AuthModuleType clientAuthModuleItem: clientAuthModule) {
                 writer.writeStartElement(prefix, "clientAuthModule", "http://geronimo.apache.org/xml/ns/geronimo-jaspi");
                 if (clientAuthModuleItem!= null) {
-                    writeAuthModuleType(writer, clientAuthModuleItem, context);
+                    writeClientAuthModuleType(writer, clientAuthModuleItem, context);
                 } else {
                     writer.writeXsiNil();
                 }
diff --git a/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ServerAuthContextTypeJAXB.java b/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ServerAuthContextTypeJAXB.java
index 1cc24f4..334b325 100644
--- a/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ServerAuthContextTypeJAXB.java
+++ b/geronimo-jaspi/src/main/java/sxc/org/apache/geronimo/components/jaspi/model/ServerAuthContextTypeJAXB.java
@@ -3,8 +3,10 @@
 
 import java.util.ArrayList;
 import java.util.List;
+
 import javax.xml.XMLConstants;
 import javax.xml.namespace.QName;
+
 import com.envoisolutions.sxc.jaxb.FieldAccessor;
 import com.envoisolutions.sxc.jaxb.JAXBObject;
 import com.envoisolutions.sxc.jaxb.LifecycleCallback;
@@ -12,12 +14,10 @@
 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.AuthModuleType;
 import org.apache.geronimo.components.jaspi.model.ServerAuthContextType;
-
-
-import static sxc.org.apache.geronimo.components.jaspi.model.AuthModuleTypeJAXB.readAuthModuleType;
-import static sxc.org.apache.geronimo.components.jaspi.model.AuthModuleTypeJAXB.writeAuthModuleType;
+import org.apache.geronimo.components.jaspi.model.AuthModuleType;
+import static sxc.org.apache.geronimo.components.jaspi.model.AuthModuleTypeJAXB.readServerAuthModuleType;
+import static sxc.org.apache.geronimo.components.jaspi.model.AuthModuleTypeJAXB.writeServerAuthModuleType;
 
 @SuppressWarnings({
     "StringEquality"
@@ -98,7 +98,7 @@
                 serverAuthContextTypeAuthenticationContextID.setObject(reader, context, serverAuthContextType, authenticationContextID);
             } else if (("serverAuthModule" == elementReader.getLocalName())&&("http://geronimo.apache.org/xml/ns/geronimo-jaspi" == elementReader.getNamespaceURI())) {
                 // ELEMENT: serverAuthModule
-                AuthModuleType serverAuthModuleItem = readAuthModuleType(elementReader, context);
+                AuthModuleType serverAuthModuleItem = readServerAuthModuleType(elementReader, context);
                 if (serverAuthModule == null) {
                     serverAuthModule = serverAuthContextTypeServerAuthModule.getObject(reader, context, serverAuthContextType);
                     if (serverAuthModule!= null) {
@@ -174,7 +174,7 @@
             for (AuthModuleType serverAuthModuleItem: serverAuthModule) {
                 writer.writeStartElement(prefix, "serverAuthModule", "http://geronimo.apache.org/xml/ns/geronimo-jaspi");
                 if (serverAuthModuleItem!= null) {
-                    writeAuthModuleType(writer, serverAuthModuleItem, context);
+                    writeServerAuthModuleType(writer, serverAuthModuleItem, context);
                 } else {
                     writer.writeXsiNil();
                 }
diff --git a/geronimo-jaspi/src/main/xsd/geronimo-jaspi.xsd b/geronimo-jaspi/src/main/xsd/geronimo-jaspi.xsd
index 09876cd..4b550f0 100644
--- a/geronimo-jaspi/src/main/xsd/geronimo-jaspi.xsd
+++ b/geronimo-jaspi/src/main/xsd/geronimo-jaspi.xsd
@@ -165,7 +165,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)
@@ -208,7 +208,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)
@@ -243,7 +243,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)
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 a999612..52107b8 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
@@ -39,23 +39,25 @@
 import org.xml.sax.SAXException;
 
 /**
- * @version $Rev:$ $Date:$
+ * @version $Rev$ $Date$
  */
 
 public class JaxbTest {
     public static final XMLInputFactory XMLINPUT_FACTORY = XMLInputFactory.newInstance();
 
+    private final int count = 2;
+
     @Test
     public void testLoad() throws Exception {
         String file = "test-jaspi.xml";
         JaspiType jaspi1 = loadJaspi(file);
-        if (jaspi1.getConfigProvider().size() != 1) throw new Exception("expected 1 configprovider, not this: " + jaspi1.getConfigProvider());
+        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");
         Writer writer = new FileWriter(newFile);
         JaspiXmlUtil.writeJaspi(jaspi1, writer);
         JaspiType jaspi2 = JaspiXmlUtil.loadJaspi(new FileReader(newFile));
-        if (jaspi2.getConfigProvider().size() != 1) throw new Exception("expected 1 configprovider, not this: " + jaspi2.getConfigProvider());
+        if (jaspi2.getConfigProvider().size() != count) throw new Exception("expected " + count + " configprovider, not this: " + jaspi2.getConfigProvider());
     }
 
     private JaspiType loadJaspi(String file) throws ParserConfigurationException, IOException, SAXException, JAXBException, XMLStreamException {
diff --git a/geronimo-jaspi/src/test/resources/test-jaspi.xml b/geronimo-jaspi/src/test/resources/test-jaspi.xml
index 0d1a060..d3d58fb 100644
--- a/geronimo-jaspi/src/test/resources/test-jaspi.xml
+++ b/geronimo-jaspi/src/test/resources/test-jaspi.xml
@@ -27,4 +27,13 @@
         <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