add a little bit of persistence

git-svn-id: https://svn.apache.org/repos/asf/geronimo/components/jaspi/trunk@676497 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/geronimo-jaspi/pom.xml b/geronimo-jaspi/pom.xml
index b3ccc60..43dc99b 100644
--- a/geronimo-jaspi/pom.xml
+++ b/geronimo-jaspi/pom.xml
@@ -32,13 +32,13 @@
     <artifactId>geronimo-jaspi</artifactId>
     <version>1.0-SNAPSHOT</version>
     <name>Geronimo JASPI implementation</name>
-    
+
     <scm>
         <connection>scm:svn:http://svn.apache.org/repos/asf/geronimo/components/jaspi/trunk</connection>
         <developerConnection>scm:svn:https://svn.apache.org/repos/asf/geronimo/components/jaspi/trunk</developerConnection>
         <url>http://svn.apache.org/viewvc/geronimo/components/jaspi/trunk</url>
     </scm>
-    
+
     <properties>
         <!--
         NOTE: Project version, to be used instead of ${pom.version} since that
@@ -52,11 +52,11 @@
 
         <!-- OSGi properties -->
         <geronimo.jaspi.osgi.export>${geronimo.jaspi.osgi.export.pkg}*;version=${version}</geronimo.jaspi.osgi.export>
-        <geronimo.jaspi.osgi.export.pkg />
-        <geronimo.jaspi.osgi.import.pkg />
-        <geronimo.jaspi.osgi.private.pkg />
+        <geronimo.jaspi.osgi.export.pkg/>
+        <geronimo.jaspi.osgi.import.pkg/>
+        <geronimo.jaspi.osgi.private.pkg/>
     </properties>
-    
+
     <dependencyManagement>
         <dependencies>
             <dependency>
@@ -65,16 +65,141 @@
                 <version>1.0-SNAPSHOT</version>
             </dependency>
 
+            <dependency>
+                <groupId>org.apache.xbean</groupId>
+                <artifactId>xbean-reflect</artifactId>
+                <version>3.4.3</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.apache.xbean</groupId>
+                <artifactId>xbean-reflect</artifactId>
+                <version>3.4.3</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.envoisolutions.sxc</groupId>
+                <artifactId>sxc-jaxb</artifactId>
+                <version>0.8-SNAPSHOT</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>stax</groupId>
+                        <artifactId>stax-api</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>org.codehaus.woodstox</groupId>
+                <artifactId>wstx-asl</artifactId>
+                <version>3.2.0</version>
+            </dependency>
+            <dependency>
+                <groupId>com.sun.xml.bind</groupId>
+                <artifactId>jaxb-impl</artifactId>
+                <version>2.0.5</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>javax.xml.bind</groupId>
+                        <artifactId>jaxb-api</artifactId>
+                    </exclusion>
+                    <exclusion>
+                        <groupId>javax.xml</groupId>
+                        <artifactId>jsr173</artifactId>
+                    </exclusion>
+                    <exclusion>
+                        <groupId>javax.activation</groupId>
+                        <artifactId>activation</artifactId>
+                    </exclusion>
+                    <exclusion>
+                        <groupId>javax.xml.bind</groupId>
+                        <artifactId>jsr173_api</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>com.sun.xml.bind</groupId>
+                <artifactId>jaxb-xjc</artifactId>
+                <version>2.0.5</version>
+            </dependency>
+
+            <dependency>
+                <groupId>javax.xml.bind</groupId>
+                <artifactId>jaxb-api</artifactId>
+                <version>2.1</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>javax.xml.bind</groupId>
+                        <artifactId>jsr173_api</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+
+            <dependency>
+                <groupId>org.apache.geronimo.specs</groupId>
+                <artifactId>geronimo-stax-api_1.0_spec</artifactId>
+                <version>1.0.1</version>
+            </dependency>
+            <dependency>
+                <groupId>org.testng</groupId>
+                <artifactId>testng</artifactId>
+                <version>5.8</version>
+                <classifier>jdk15</classifier>
+            </dependency>
+
+
         </dependencies>
     </dependencyManagement>
 
-        <dependencies>
-            <dependency>
-                <groupId>org.apache.geronimo.specs</groupId>
-                <artifactId>geronimo-jaspi_1.0_spec</artifactId>
-            </dependency>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-jaspi_1.0_spec</artifactId>
+        </dependency>
 
-        </dependencies>
+        <dependency>
+            <groupId>org.apache.xbean</groupId>
+            <artifactId>xbean-reflect</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.envoisolutions.sxc</groupId>
+            <artifactId>sxc-jaxb</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.woodstox</groupId>
+            <artifactId>wstx-asl</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-impl</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-xjc</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.xml.bind</groupId>
+            <artifactId>jaxb-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-stax-api_1.0_spec</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <classifier>jdk15</classifier>
+            <scope>test</scope>
+        </dependency>
+
+
+
+    </dependencies>
     <build>
         <pluginManagement>
             <plugins>
@@ -83,11 +208,11 @@
                     <artifactId>maven-enforcer-plugin</artifactId>
                     <version>1.0-alpha-3</version>
                 </plugin>
-                
+
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-surefire-plugin</artifactId>
-                    <version>2.3</version>
+                    <version>2.4.2</version>
                     <configuration>
                         <redirectTestOutputToFile>true</redirectTestOutputToFile>
                     </configuration>
@@ -98,7 +223,7 @@
                     <artifactId>maven-install-plugin</artifactId>
                     <version>2.2</version>
                 </plugin>
-                
+
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-jar-plugin</artifactId>
@@ -118,6 +243,25 @@
         </pluginManagement>
 
         <plugins>
+            <!--
+                     <plugin>
+                      <groupId>com.envoisolutions.sxc</groupId>
+                      <artifactId>sxc-jaxb-maven-plugin</artifactId>
+                      <version>0.8-SNAPSHOT</version>
+                      <executions>
+                        <execution>
+                          <configuration>
+                            <classes>
+                              <class>org.apache.geronimo.components.jaspi</class>
+                            </classes>
+                          </configuration>
+                          <goals>
+                            <goal>generate</goal>
+                          </goals>
+                      </execution>
+                    </executions>
+                  </plugin>
+            -->
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-enforcer-plugin</artifactId>
@@ -133,7 +277,7 @@
                                 <requireJavaVersion>
                                     <version>[1.5,1.6)</version>
                                 </requireJavaVersion>
-                                
+
                                 <!-- Allow any Maven >= 2.0.5 -->
                                 <requireMavenVersion>
                                     <version>[2.0.9,)</version>
@@ -143,7 +287,7 @@
                     </execution>
                 </executions>
             </plugin>
-            
+
             <plugin>
                 <groupId>org.apache.geronimo.genesis.plugins</groupId>
                 <artifactId>tools-maven-plugin</artifactId>
@@ -162,7 +306,7 @@
                     </execution>
                 </executions>
             </plugin>
-            
+
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
@@ -183,30 +327,49 @@
                     <linkModules>true</linkModules>
                 </configuration>
             </plugin>
-<!--
+            <!--
+                        <plugin>
+                            <groupId>org.apache.felix</groupId>
+                            <artifactId>maven-bundle-plugin</artifactId>
+                            <version>1.2.0</version>
+                            <extensions>true</extensions>
+                            <executions>
+                                <execution>
+                                    <goals>
+                                        <goal>bundle</goal>
+                                    </goals>
+                                </execution>
+                            </executions>
+                            <configuration>
+                                <instructions>
+                                    <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
+                                    <Export-Package>${geronimo.jaspi.osgi.export}</Export-Package>
+                                    <Import-Package>${geronimo.jaspi.osgi.import.pkg}*</Import-Package>
+                                    <Private-Package>${geronimo.jaspi.osgi.private.pkg}</Private-Package>
+                                </instructions>
+                                <unpackBundle>true</unpackBundle>
+                            </configuration>
+                        </plugin>
+            -->
+            <!--
             <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <version>1.2.0</version>
-                <extensions>true</extensions>
+                <groupId>org.jvnet.jaxb2.maven2</groupId>
+                <artifactId>maven-jaxb2-plugin</artifactId>
+                <version>0.5</version>
                 <executions>
                     <execution>
                         <goals>
-                            <goal>bundle</goal>
+                            <goal>generate</goal>
                         </goals>
                     </execution>
                 </executions>
                 <configuration>
-                    <instructions>
-                        <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
-                        <Export-Package>${geronimo.jaspi.osgi.export}</Export-Package>
-                        <Import-Package>${geronimo.jaspi.osgi.import.pkg}*</Import-Package>
-                        <Private-Package>${geronimo.jaspi.osgi.private.pkg}</Private-Package>
-                    </instructions>
-                    <unpackBundle>true</unpackBundle>
+                    <schemaDirectory>src/main/xsd</schemaDirectory>
+                    <packageName>org.apache.geronimo.components.jaspi.model</packageName>
+                    <extension>true</extension>
                 </configuration>
             </plugin>
--->
+    -->
         </plugins>
     </build>
 
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 b713fe1..10339e4 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
@@ -16,10 +16,10 @@
  */

 package org.apache.geronimo.components.jaspi;

 

-import java.lang.reflect.Constructor;

-import java.lang.reflect.InvocationTargetException;

-import java.security.PrivilegedActionException;

-import java.security.PrivilegedExceptionAction;

+import java.io.File;

+import java.io.FileReader;

+import java.io.FileWriter;

+import java.io.IOException;

 import java.util.ArrayList;

 import java.util.HashMap;

 import java.util.List;

@@ -30,6 +30,14 @@
 import javax.security.auth.message.config.AuthConfigFactory;

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

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

+import javax.xml.bind.JAXBException;

+import javax.xml.parsers.ParserConfigurationException;

+import javax.xml.stream.XMLStreamException;

+

+import org.apache.geronimo.components.jaspi.model.ConfigProviderType;

+import org.apache.geronimo.components.jaspi.model.JaspiType;

+import org.apache.geronimo.components.jaspi.model.JaspiXmlUtil;

+import org.xml.sax.SAXException;

 

 /**

  * Implementation of the AuthConfigFactory. 

@@ -37,8 +45,14 @@
 public class AuthConfigFactoryImpl extends AuthConfigFactory {

 

     private static ClassLoader contextClassLoader;

-    private Map<String, Context> registrations = new HashMap<String, Context>();

-    

+    private final Map<String, ConfigProviderType> registrations = new HashMap<String, ConfigProviderType>();

+    private JaspiType jaspiType = new JaspiType();

+

+    private final ClassLoaderLookup classLoaderLookup;

+    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

                         .doPrivileged(new java.security.PrivilegedAction<ClassLoader>() {

@@ -47,10 +61,21 @@
                             }

                         });

     }

-    

-    public AuthConfigFactoryImpl() throws AuthException {

+

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

+        this.classLoaderLookup = classLoaderLookup;

+        this.configFile = configFile;

         loadConfig();

     }

+

+    public AuthConfigFactoryImpl() throws AuthException {

+        this(new ClassLoaderLookup() {

+

+            public ClassLoader getClassLoader(String name) {

+                return contextClassLoader;

+            }

+        }, staticConfigFile);

+    }

     

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

         SecurityManager sm = System.getSecurityManager();

@@ -58,8 +83,8 @@
             sm.checkPermission(new AuthPermission("detachAuthListener"));

         }

         List<String> ids = new ArrayList<String>();

-        for (Map.Entry<String, Context> entry : registrations.entrySet()) {

-            Context ctx = entry.getValue();

+        for (Map.Entry<String, ConfigProviderType> entry : registrations.entrySet()) {

+            ConfigProviderType ctx = entry.getValue();

             if ((layer == null || layer.equals(ctx.getMessageLayer())) &&

                     (appContext == null || appContext.equals(ctx.getAppContext()))) {

                 if (ctx.getListeners().remove(listener)) {

@@ -71,7 +96,13 @@
     }

 

     public synchronized AuthConfigProvider getConfigProvider(String layer, String appContext, RegistrationListener listener) {

-        Context ctx = registrations.get(getRegistrationKey(layer, appContext));

+        if (layer == null) {

+            throw new NullPointerException("messageLayer");

+        }

+        if (appContext == null) {

+            throw new NullPointerException("appContext");

+        }

+        ConfigProviderType ctx = registrations.get(getRegistrationKey(layer, appContext));

         if (ctx == null) {

             ctx = registrations.get(getRegistrationKey(null, appContext));

         }

@@ -96,8 +127,8 @@
 

     public synchronized String[] getRegistrationIDs(AuthConfigProvider provider) {

         List<String> ids = new ArrayList<String>();

-        for (Map.Entry<String, Context> entry : registrations.entrySet()) {

-            Context ctx = entry.getValue();

+        for (Map.Entry<String, ConfigProviderType> entry : registrations.entrySet()) {

+            ConfigProviderType ctx = entry.getValue();

             if (provider == null ||

                     provider.getClass().getName().equals(ctx.getProvider().getClass().getName())) {

                 ids.add(entry.getKey());

@@ -119,7 +150,7 @@
         if (sm != null) {

             sm.checkPermission(new AuthPermission("registerAuthConfigProvider"));

         }

-        return registerConfigProvider(authConfigProvider, layer, appContext, description, false, null);

+        return registerConfigProvider(authConfigProvider, layer, appContext, description, false, null, null);

     }

 

     public synchronized String registerConfigProvider(final String className, final Map constructorParam, String layer, String appContext, String description) throws AuthException, SecurityException {

@@ -127,47 +158,42 @@
         if (sm != null) {

             sm.checkPermission(new AuthPermission("registerAuthConfigProvider"));

         }

-        AuthConfigProvider authConfigProvider;

-        try {

-            authConfigProvider = 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, contextClassLoader);

-                    Constructor<? extends AuthConfigProvider> cnst = cl.getConstructor(Map.class);

-                    return cnst.newInstance(constructorParam);

-                }

-            });

-        } 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);

-        }

-        String key = registerConfigProvider(authConfigProvider, layer, appContext, description, true, constructorParam);

+        String key = registerConfigProvider(null, layer, appContext, description, true, constructorParam, className);

         saveConfig();

         return key;

     }

 

-    private String registerConfigProvider(AuthConfigProvider provider, String layer, String appContext, String description, boolean persistent, Map<String, String> constructorParam) throws AuthException {

+    private String registerConfigProvider(AuthConfigProvider provider, String layer, String appContext, String description, boolean persistent, Map<String, String> constructorParam, String className) throws AuthException {

         String key = getRegistrationKey(layer, appContext);

         // Get or create context

-        Context ctx = registrations.get(key);

+        ConfigProviderType ctx = registrations.get(key);

         if (ctx == null) {

-            ctx = new Context(layer, appContext, persistent);

+            ctx = new ConfigProviderType(layer, appContext, persistent);

         } else {

             if (persistent != ctx.isPersistent()) {

                 throw new IllegalArgumentException("Cannot change the persistence state");

             }

         }

         // Create provider

-        ctx.setProvider(provider);

         ctx.setDescription(description);

         registrations.put(key, ctx);

+        if (persistent) {

+            if (provider != null) {

+                throw new IllegalStateException("Config provider supplied but should be created");

+            }

+            ctx.setClassName(className);

+            ctx.setProperties(constructorParam);

+            ctx.createAuthConfigProvider(classLoaderLookup);

+            if (!jaspiType.getConfigProvider().contains(ctx)) {

+                jaspiType.getConfigProvider().add(ctx);

+            }

+        } else {

+            if (provider == null) {

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

+            }

+            ctx.setProvider(provider);

+        }

+

         // Notify listeners

         List<RegistrationListener> listeners = ctx.getListeners();

         for (RegistrationListener listener : listeners) {

@@ -182,7 +208,13 @@
         if (sm != null) {

             sm.checkPermission(new AuthPermission("removeAuthRegistration"));

         }

-        Context ctx = registrations.remove(registrationID);

+        ConfigProviderType ctx = registrations.remove(registrationID);

+        jaspiType.getConfigProvider().remove(ctx);

+        try {

+            saveConfig();

+        } catch (AuthException e) {

+            throw new SecurityException(e);

+        }

         if (ctx != null) {

             List<RegistrationListener> listeners = ctx.getListeners();

             for (RegistrationListener listener : listeners) {

@@ -198,68 +230,47 @@
     }

     

     private void loadConfig() throws AuthException {

-        // TODO: load configuration file

+        try {

+            FileReader in = new FileReader(configFile);

+            try {

+                jaspiType = JaspiXmlUtil.loadJaspi(in);

+                for (ConfigProviderType configProviderType: jaspiType.getConfigProvider()) {

+                    String key = getRegistrationKey(configProviderType.getMessageLayer(), configProviderType.getAppContext());

+                    configProviderType.createAuthConfigProvider(classLoaderLookup);

+                    registrations.put(key, configProviderType);

+                }

+            } finally {

+                in.close();

+            }

+        } catch (ParserConfigurationException e) {

+            throw (AuthException)new AuthException("Could not read config").initCause(e);

+        } catch (IOException e) {

+            throw (AuthException)new AuthException("Could not read config").initCause(e);

+        } catch (SAXException e) {

+            throw (AuthException)new AuthException("Could not read config").initCause(e);

+        } catch (JAXBException e) {

+            throw (AuthException)new AuthException("Could not read config").initCause(e);

+        } catch (XMLStreamException e) {

+            throw (AuthException)new AuthException("Could not read config").initCause(e);

+        }

     }

     

     private void saveConfig() throws AuthException {

-        // TODO: save configuration file

-    }

-    

-    private static class Context implements RegistrationContext {

-

-        private final String layer;

-        private final String appContext;

-        private final List<RegistrationListener> listeners = new ArrayList<RegistrationListener>();

-        private String description;

-        private AuthConfigProvider provider;

-        private final boolean persistent;

-        private Map<String, String> constructorParam;

-        

-        public Context(String layer, String appContext, boolean persistent) {

-            this.layer = layer;

-            this.appContext = appContext;

-            this.persistent = persistent;

-        }

-        

-        public String getAppContext() {

-            return appContext;

-        }

-

-        public String getMessageLayer() {

-            return layer;

-        }

-

-        public boolean isPersistent() {

-            return persistent;

-        }

-

-        public String getDescription() {

-            return description;

-        }

-

-        public List<RegistrationListener> getListeners() {

-            return listeners;

-        }

-        

-        public AuthConfigProvider getProvider() {

-            return provider;

-        }

-

-        public void setProvider(AuthConfigProvider provider) {

-            this.provider = provider;

-        }

-

-        public void setDescription(String description) {

-            this.description = description;

-        }

-

-        public Map<String, String> getConstructorParam() {

-            return constructorParam;

-        }

-

-        public void setConstructorParam(Map<String, String> constructorParam) {

-            this.constructorParam = constructorParam;

+        try {

+            FileWriter out = new FileWriter(configFile);

+            try {

+                JaspiXmlUtil.writeJaspi(jaspiType, out);

+            } finally {

+                out.close();

+            }

+        } catch (IOException e) {

+            throw (AuthException)new AuthException("Could not write config").initCause(e);

+        } catch (XMLStreamException e) {

+            throw (AuthException)new AuthException("Could not write config").initCause(e);

+        } catch (JAXBException e) {

+            throw (AuthException)new AuthException("Could not write config").initCause(e);

         }

     }

     

+

 }

diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/ClassLoaderLookup.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/ClassLoaderLookup.java
new file mode 100644
index 0000000..df0a87b
--- /dev/null
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/ClassLoaderLookup.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+/**
+ * @version $Rev:$ $Date:$
+ */
+public interface ClassLoaderLookup {
+
+    ClassLoader getClassLoader(String name);
+    
+}
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
new file mode 100644
index 0000000..a2ff289
--- /dev/null
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ConfigProviderType.java
@@ -0,0 +1,288 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.1.5-b01-fcs 
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
+// Any modifications to this file will be lost upon recompilation of the source schema. 
+// Generated on: 2008.07.12 at 02:51:39 PM PDT 
+//
+
+
+package org.apache.geronimo.components.jaspi.model;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+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.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+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.AuthException;
+
+import org.apache.geronimo.components.jaspi.ClassLoaderLookup;
+
+
+/**
+ * <p>Java class for configProviderType complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="configProviderType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &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="description" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         &lt;element name="className" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         &lt;element name="properties" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         &lt;element name="persistent" type="{http://www.w3.org/2001/XMLSchema}boolean" minOccurs="0"/>
+ *       &lt;/sequence>
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "configProviderType", propOrder = {
+    "messageLayer",
+    "appContext",
+    "description",
+    "className",
+    "properties",
+    "persistent",
+    "classLoaderName"
+})
+public class ConfigProviderType
+    implements AuthConfigFactory.RegistrationContext, Serializable
+{
+
+    private final static long serialVersionUID = 12343L;
+
+    protected String messageLayer;
+    protected String appContext;
+    protected String description;
+    @XmlElement(required = true)
+    protected String className;
+    @XmlElement(required = true)
+    @XmlJavaTypeAdapter(StringMapAdapter.class)
+    protected Map<String, String> properties;
+    protected boolean persistent;
+    protected String classLoaderName;
+
+    @XmlTransient
+    private final List<RegistrationListener> listeners = new ArrayList<RegistrationListener>();
+    @XmlTransient
+    private AuthConfigProvider provider;
+
+
+    public ConfigProviderType() {
+    }
+
+    public ConfigProviderType(String messageLayer, String appContext, boolean persistent) {
+        this.messageLayer = messageLayer;
+        this.appContext = appContext;
+        this.persistent = persistent;
+    }
+
+    /**
+     * Gets the value of the messageLayer property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getMessageLayer() {
+        return messageLayer;
+    }
+
+    /**
+     * Sets the value of the messageLayer property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void getMessageLayer(String value) {
+        this.messageLayer = value;
+    }
+
+    /**
+     * Gets the value of the appContext property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getAppContext() {
+        return appContext;
+    }
+
+    /**
+     * Sets the value of the appContext property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setAppContext(String value) {
+        this.appContext = value;
+    }
+
+    /**
+     * Gets the value of the description property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * Sets the value of the description property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setDescription(String value) {
+        this.description = value;
+    }
+
+    /**
+     * Gets the value of the className property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getClassName() {
+        return className;
+    }
+
+    /**
+     * Sets the value of the className property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setClassName(String value) {
+        this.className = value;
+    }
+
+    /**
+     * Gets the value of the properties property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public Map<String, String> getProperties() {
+        return properties;
+    }
+
+    /**
+     * Sets the value of the properties property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setProperties(Map<String, String> value) {
+        this.properties = value;
+    }
+
+    /**
+     * Gets the value of the persistent property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link Boolean }
+     *     
+     */
+    public boolean isPersistent() {
+        return persistent;
+    }
+
+    /**
+     * Sets the value of the persistent property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link Boolean }
+     *     
+     */
+    public void setPersistent(boolean value) {
+        this.persistent = value;
+    }
+
+    public List<RegistrationListener> getListeners() {
+        return listeners;
+    }
+
+    public AuthConfigProvider getProvider() {
+        return provider;
+    }
+
+    public void setProvider(AuthConfigProvider provider) {
+        this.provider = provider;
+    }
+
+    public String getClassLoaderName() {
+        return classLoaderName;
+    }
+
+    public void setClassLoaderName(String classLoaderName) {
+        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);
+                }
+            });
+        } 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/JaspiType.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/JaspiType.java
new file mode 100644
index 0000000..ff409de
--- /dev/null
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/JaspiType.java
@@ -0,0 +1,80 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.1.5-b01-fcs 
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
+// Any modifications to this file will be lost upon recompilation of the source schema. 
+// Generated on: 2008.07.12 at 02:51:39 PM PDT 
+//
+
+
+package org.apache.geronimo.components.jaspi.model;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.geronimo.components.jaspi.model.ConfigProviderType;
+
+
+/**
+ * <p>Java class for jaspiType complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="jaspiType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="configProvider" type="{http://geronimo.apache.org/xml/ns/geronimo-jaspi}configProviderType" maxOccurs="unbounded" minOccurs="0"/>
+ *       &lt;/sequence>
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "jaspiType", propOrder = {
+    "configProvider"
+})
+public class JaspiType
+    implements Serializable
+{
+
+    private final static long serialVersionUID = 12343L;
+    protected List<ConfigProviderType> configProvider;
+
+    /**
+     * Gets the value of the configProvider property.
+     * 
+     * <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 configProvider property.
+     * 
+     * <p>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getConfigProvider().add(newItem);
+     * </pre>
+     * 
+     * 
+     * <p>
+     * Objects of the following type(s) are allowed in the list
+     * {@link ConfigProviderType }
+     * 
+     * 
+     */
+    public List<ConfigProviderType> getConfigProvider() {
+        if (configProvider == null) {
+            configProvider = new ArrayList<ConfigProviderType>();
+        }
+        return this.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
new file mode 100644
index 0000000..6693c0a
--- /dev/null
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/JaspiXmlUtil.java
@@ -0,0 +1,74 @@
+/*
+ * 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.io.Writer;
+import java.io.Reader;
+import java.io.IOException;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.xml.sax.SAXException;
+
+/**
+ * @version $Rev:$ $Date:$
+ */
+public class JaspiXmlUtil {
+    public static final XMLInputFactory XMLINPUT_FACTORY = XMLInputFactory.newInstance();
+    public static final JAXBContext JASPI_CONTEXT;
+
+    static {
+        try {
+            JASPI_CONTEXT = JAXBContext.newInstance(JaspiType.class);
+        } catch (JAXBException e) {
+            throw new RuntimeException("Could not create jaxb contexts for plugin types", e);
+        }
+    }
+
+    public static void writeJaspi(JaspiType metadata, Writer out) throws XMLStreamException, JAXBException {
+        Marshaller marshaller = JASPI_CONTEXT.createMarshaller();
+        marshaller.setProperty("jaxb.formatted.output", true);
+        JAXBElement<JaspiType> element = new ObjectFactory().createJaspi(metadata);
+        marshaller.marshal(element, out);
+    }
+
+
+    public static JaspiType loadJaspi(Reader in) throws ParserConfigurationException, IOException, SAXException, JAXBException, XMLStreamException {
+        XMLStreamReader xmlStream = XMLINPUT_FACTORY.createXMLStreamReader(in);
+        return loadJaspi(xmlStream);
+    }
+
+    public static JaspiType loadJaspi(XMLStreamReader in) throws ParserConfigurationException, IOException, SAXException, JAXBException, XMLStreamException {
+        Unmarshaller unmarshaller = JASPI_CONTEXT.createUnmarshaller();
+        JAXBElement<JaspiType> element = unmarshaller.unmarshal(in, JaspiType.class);
+        JaspiType rbac = element.getValue();
+        return rbac;
+    }
+
+}
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ObjectFactory.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ObjectFactory.java
new file mode 100644
index 0000000..ebe6fa6
--- /dev/null
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/ObjectFactory.java
@@ -0,0 +1,71 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.1.5-b01-fcs 
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
+// Any modifications to this file will be lost upon recompilation of the source schema. 
+// Generated on: 2008.07.12 at 02:51:39 PM PDT 
+//
+
+
+package org.apache.geronimo.components.jaspi.model;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElementDecl;
+import javax.xml.bind.annotation.XmlRegistry;
+import javax.xml.namespace.QName;
+
+import org.apache.geronimo.components.jaspi.model.ConfigProviderType;
+import org.apache.geronimo.components.jaspi.model.JaspiType;
+
+
+/**
+ * This object contains factory methods for each 
+ * Java content interface and Java element interface 
+ * generated in the org.apache.geronimo.xml.ns.geronimo_jaspi package. 
+ * <p>An ObjectFactory allows you to programatically 
+ * construct new instances of the Java representation 
+ * for XML content. The Java representation of XML 
+ * content can consist of schema derived interfaces 
+ * and classes representing the binding of schema 
+ * type definitions, element declarations and model 
+ * groups.  Factory methods for each of these are 
+ * provided in this class.
+ * 
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+    private final static QName _Jaspi_QNAME = new QName("http://geronimo.apache.org/xml/ns/geronimo-jaspi", "jaspi");
+
+    /**
+     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.apache.geronimo.xml.ns.geronimo_jaspi
+     * 
+     */
+    public ObjectFactory() {
+    }
+
+    /**
+     * Create an instance of {@link ConfigProviderType }
+     * 
+     */
+    public ConfigProviderType createConfigProviderType() {
+        return new ConfigProviderType();
+    }
+
+    /**
+     * Create an instance of {@link JaspiType }
+     * 
+     */
+    public JaspiType createJaspiType() {
+        return new JaspiType();
+    }
+
+    /**
+     * Create an instance of {@link JAXBElement }{@code <}{@link org.apache.geronimo.components.jaspi.model.JaspiType }{@code >}}
+     * 
+     */
+    @XmlElementDecl(namespace = "http://geronimo.apache.org/xml/ns/geronimo-jaspi", name = "jaspi")
+    public JAXBElement<JaspiType> createJaspi(JaspiType value) {
+        return new JAXBElement<JaspiType>(_Jaspi_QNAME, JaspiType.class, null, value);
+    }
+
+}
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/StringMapAdapter.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/StringMapAdapter.java
new file mode 100644
index 0000000..b0411ab
--- /dev/null
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/StringMapAdapter.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.model;
+
+import java.util.Properties;
+import java.util.Map;
+import java.util.HashMap;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+/**
+ * @version $Rev:$ $Date:$
+ */
+public class StringMapAdapter extends XmlAdapter<String, Map<String, String>> {
+    public Map<String, String> unmarshal(String s) throws Exception {
+        Properties properties = new Properties();
+        ByteArrayInputStream in = new ByteArrayInputStream(s.getBytes());
+        properties.load(in);
+        Map<String, String> map = new HashMap<String, String>(properties.size());
+        for (Map.Entry entry: properties.entrySet()) {
+            map.put((String)entry.getKey(), (String)entry.getValue());
+        }
+        return map;
+    }
+
+    public String marshal(Map<String, String> map) throws Exception {
+        Properties properties = new Properties();
+        properties.putAll(map);
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        properties.store(out, null);
+        return new String(out.toByteArray());
+    }
+
+}
diff --git a/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/package-info.java b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/package-info.java
new file mode 100644
index 0000000..19c0051
--- /dev/null
+++ b/geronimo-jaspi/src/main/java/org/apache/geronimo/components/jaspi/model/package-info.java
@@ -0,0 +1,9 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.1.5-b01-fcs
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2008.07.12 at 02:51:39 PM PDT
+//
+
+@javax.xml.bind.annotation.XmlSchema(namespace = "http://geronimo.apache.org/xml/ns/geronimo-jaspi", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+package org.apache.geronimo.components.jaspi.model;
diff --git a/geronimo-jaspi/src/main/resources/META-INF/sun-jaxb.episode b/geronimo-jaspi/src/main/resources/META-INF/sun-jaxb.episode
new file mode 100644
index 0000000..b89e6c2
--- /dev/null
+++ b/geronimo-jaspi/src/main/resources/META-INF/sun-jaxb.episode
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<bindings version="2.1" xmlns="http://java.sun.com/xml/ns/jaxb">
+  <!--
+
+This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.1.5-b01-fcs
+See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+Any modifications to this file will be lost upon recompilation of the source schema.
+Generated on: 2008.07.12 at 02:26:00 PM PDT
+
+  -->
+  <bindings scd="x-schema::tns" xmlns:tns="http://geronimo.apache.org/xml/ns/geronimo-jaspi">
+    <schemaBindings map="false"/>
+    <bindings scd="~tns:configProviderType">
+      <class ref="org.apache.geronimo.components.jaspi.ConfigProviderType"/>
+    </bindings>
+    <bindings scd="~tns:jaspiType">
+      <class ref="org.apache.geronimo.components.jaspi.JaspiType"/>
+    </bindings>
+  </bindings>
+</bindings>
+
diff --git a/geronimo-jaspi/src/main/xsd/geronimo-jaspi.xsd b/geronimo-jaspi/src/main/xsd/geronimo-jaspi.xsd
new file mode 100644
index 0000000..b1b384f
--- /dev/null
+++ b/geronimo-jaspi/src/main/xsd/geronimo-jaspi.xsd
@@ -0,0 +1,143 @@
+<?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.
+-->
+
+<xs:schema targetNamespace="http://geronimo.apache.org/xml/ns/geronimo-jaspi"
+           xmlns:jaspi="http://geronimo.apache.org/xml/ns/geronimo-jaspi"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+           xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
+           elementFormDefault="qualified"
+           attributeFormDefault="unqualified"
+           jaxb:extensionBindingPrefixes="xjc"
+           jaxb:version="2.0">
+
+
+    <xs:annotation>
+        <xs:appinfo>
+            <jaxb:globalBindings>
+                <xjc:serializable uid="12343"/>
+            </jaxb:globalBindings>
+        </xs:appinfo>
+    </xs:annotation>
+
+    <xs:annotation>
+        <xs:documentation>
+            This is an XML Schema Definition for Geronimo JASPI implementation configurations.
+        </xs:documentation>
+    </xs:annotation>
+
+    <xs:element name="jaspi" type="jaspi:jaspiType">
+        <xs:annotation>
+            <xs:documentation>
+                The jaspi element is the root element of the jaspi configuration file.
+            </xs:documentation>
+        </xs:annotation>
+    </xs:element>
+
+    <xs:complexType name="jaspiType">
+        <xs:sequence>
+            <xs:element name="configProvider" type="jaspi:configProviderType" minOccurs="0" maxOccurs="unbounded">
+                <xs:annotation>
+                    <xs:documentation>
+                        Reference to configProvider element defined later in this xsd.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+
+    <!--<xs:complexType name="emptyType"/>-->
+
+
+    <xs:complexType name="configProviderType">
+        <xs:sequence>
+            <xs:annotation>
+                <xs:documentation>
+                    configProviderType configures a AuthConfigProvider
+                </xs:documentation>
+            </xs:annotation>
+
+            <xs:element name="messageLayer" type="xs:string" minOccurs="0">
+                <xs:annotation>
+                    <xs:documentation>
+                        The attribute provide the name-value pair of
+                        various attributes for this GBean. The value of
+                        the attributes is specified by value of this
+                        element.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="appContext" type="xs:string" minOccurs="0">
+                <xs:annotation>
+                    <xs:documentation>
+                        The xml-attribute specifies the value of
+                        particular attribute in XML format, which will
+                        be interpreted by a component running in the
+                        system, which convert it to single value for
+                        this attribute.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="description" type="xs:string" minOccurs="0">
+                <xs:annotation>
+                    <xs:documentation>
+                        The "reference" element specifies the value of a
+                        particular reference for this GBean in simplest
+                        form. It holds the reference to the GBean that
+                        matches the single pattern specified here, if no
+                        value is specified it will refer to all the
+                        matching GBeans.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="className" type="xs:string">
+                <xs:annotation>
+                    <xs:documentation>
+                        The "references" element specifies the value of
+                        a particular reference for this GBean matching
+                        multiple pattern elements.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="properties"
+                        type="xs:string" minOccurs="0">
+                <xs:annotation>
+                    <xs:documentation>
+                        The xml-reference specifies the value of
+                        particular reference in XML format, which will
+                        be interpreted by a component running in the
+                        system, which convert it to single value for
+                        this reference.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="persistent" type="xs:boolean" minOccurs="0">
+                <xs:annotation>
+                    <xs:documentation>
+                        The element "dependency" is used to resolve
+                        dependencies at GBean level. This is normally
+                        only used if for some reason the GBeans within a
+                        module must be started in a certain order that
+                        is not reflected in the references between them.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+
+</xs:schema>
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
new file mode 100644
index 0000000..10591c6
--- /dev/null
+++ b/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/AuthConfigFactoryImplTest.java
@@ -0,0 +1,163 @@
+/**

+ * 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;

+

+import java.io.File;

+import java.net.URL;

+

+import javax.security.auth.message.AuthException;

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

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

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

+

+import junit.framework.TestCase;

+

+import org.apache.geronimo.components.jaspi.providers.BadConstructorProvider;

+import org.apache.geronimo.components.jaspi.providers.BadImplementProvider;

+import org.apache.geronimo.components.jaspi.providers.DummyProvider;

+

+public class AuthConfigFactoryImplTest extends TestCase {

+

+    protected void setUp() throws Exception {

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

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

+        AuthConfigFactory.setFactory(null);

+    }

+    

+    public void testFactory() throws Exception {

+        AuthConfigFactory factory1 = AuthConfigFactory.getFactory();

+        assertNotNull(factory1);

+        AuthConfigFactory factory2 = AuthConfigFactory.getFactory();

+        assertNotNull(factory2);

+        assertSame(factory1, factory2);

+    }

+    

+    public void testBadConstructorProvider() throws Exception {

+        try {

+            AuthConfigFactory factory = AuthConfigFactory.getFactory();

+            factory.registerConfigProvider(BadConstructorProvider.class.getName(), null, "layer1", "appContext1", "description");

+            fail("An exception should have been thrown");

+        } catch (AuthException e) {

+            //e.printStackTrace();

+        }

+    }

+    

+    public void testBadImplementProvider() throws Exception {

+        try {

+            AuthConfigFactory factory = AuthConfigFactory.getFactory();

+            factory.registerConfigProvider(BadImplementProvider.class.getName(), null, "layer2", "appContext2", "description");

+            fail("An exception should have been thrown");

+        } catch (AuthException e) {

+            //e.printStackTrace();

+        }

+    }

+    

+    public void testRegisterUnregister() throws Exception {

+        AuthConfigFactory factory = AuthConfigFactory.getFactory();

+        String regId = factory.registerConfigProvider(DummyProvider.class.getName(), null, "layer3", "appContext3", "description");

+        assertNotNull(regId);

+        RegistrationContext regContext = factory.getRegistrationContext(regId);

+        assertNotNull(regContext);

+        assertEquals("layer3", regContext.getMessageLayer());

+        assertEquals("appContext3", regContext.getAppContext());

+        assertEquals("description", regContext.getDescription());

+

+        assertTrue(factory.removeRegistration(regId));

+        

+        regContext = factory.getRegistrationContext(regId);

+        assertNull(regContext);

+    }

+    

+    public void testProviderWithLayerAndContext() throws Exception {

+        AuthConfigFactory factory = AuthConfigFactory.getFactory();

+        String registrationID = factory.registerConfigProvider(DummyProvider.class.getName(), null, "layer4", "appContext4", "description");

+

+        assertNotNull(factory.getConfigProvider("layer4", "appContext4", null));

+        assertNull(factory.getConfigProvider("layer4", "bad", null));

+        assertNull(factory.getConfigProvider("bad", "appContext4", null));

+//        assertNull(factory.getConfigProvider(null, null, null));

+        factory.removeRegistration(registrationID);

+        assertNull(factory.getRegistrationContext(registrationID));

+    }

+    

+    public void testProviderWithLayer() throws Exception {

+        AuthConfigFactory factory = AuthConfigFactory.getFactory();

+        String registrationID = factory.registerConfigProvider(DummyProvider.class.getName(), null, "layer5", null, "description");

+

+        assertNotNull(factory.getConfigProvider("layer5", "appContext5", null));

+//        assertNotNull(factory.getConfigProvider("layer5", null, null));

+        assertNotNull(factory.getConfigProvider("layer5", "bad", null));

+        assertNull(factory.getConfigProvider("bad", "appContext5", null));

+//        assertNull(factory.getConfigProvider(null, null, null));

+        factory.removeRegistration(registrationID);

+        assertNull(factory.getRegistrationContext(registrationID));

+    }

+    

+    public void testProviderContextLayer() throws Exception {

+        AuthConfigFactory factory = AuthConfigFactory.getFactory();

+        String registrationID = factory.registerConfigProvider(DummyProvider.class.getName(), null, null, "appContext6", "description");

+

+        assertNotNull(factory.getConfigProvider("layer6", "appContext6", null));

+//        assertNull(factory.getConfigProvider("layer6", null, null));

+        assertNull(factory.getConfigProvider("layer6", "bad", null));

+        assertNotNull(factory.getConfigProvider("bad", "appContext6", null));

+//        assertNull(factory.getConfigProvider(null, null, null));

+        factory.removeRegistration(registrationID);

+        assertNull(factory.getRegistrationContext(registrationID));

+    }

+    

+    public void testProviderDefault() throws Exception {

+        AuthConfigFactory factory = AuthConfigFactory.getFactory();

+        String registrationID = factory.registerConfigProvider(DummyProvider.class.getName(), null, null, null, "description");

+

+        assertNotNull(factory.getConfigProvider("layer7", "appContext7", null));

+//        assertNotNull(factory.getConfigProvider("layer7", null, null));

+        assertNotNull(factory.getConfigProvider("layer7", "bad", null));

+        assertNotNull(factory.getConfigProvider("bad", "appContext7", null));

+        assertNotNull(factory.getConfigProvider("bad", "bad", null));

+        factory.removeRegistration(registrationID);

+        assertNull(factory.getRegistrationContext(registrationID));

+    }

+    

+    public void testListenerOnRegister() throws Exception {

+        AuthConfigFactory factory = AuthConfigFactory.getFactory();

+        String registrationID = factory.registerConfigProvider(DummyProvider.class.getName(), null, null, null, "description");

+        DummyListener listener = new DummyListener();

+        assertNotNull(factory.getConfigProvider("foo", "bar", listener));

+        factory.registerConfigProvider(DummyProvider.class.getName(), null, null, null, "description");

+        assertTrue(listener.notified);

+        factory.removeRegistration(registrationID);

+        assertNull(factory.getRegistrationContext(registrationID));

+    }

+    

+    public void testListenerOnUnregister() throws Exception {

+        AuthConfigFactory factory = AuthConfigFactory.getFactory();

+        String regId = factory.registerConfigProvider(DummyProvider.class.getName(), null, null, null, "description");

+        DummyListener listener = new DummyListener();

+        assertNotNull(factory.getConfigProvider("foo", "bar", listener));

+        factory.removeRegistration(regId);

+        assertTrue(listener.notified);

+    }

+    

+    public static class DummyListener implements RegistrationListener {

+        public boolean notified = true;

+        public void notify(String layer, String appContext) {

+            notified = true;

+        }

+    }

+    

+}

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
new file mode 100644
index 0000000..25e5f02
--- /dev/null
+++ b/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/model/JaxbTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+
+import org.testng.annotations.Test;
+import org.xml.sax.SAXException;
+
+/**
+ * @version $Rev:$ $Date:$
+ */
+
+public class JaxbTest {
+    public static final XMLInputFactory XMLINPUT_FACTORY = XMLInputFactory.newInstance();
+
+    @Test
+    public void testLoad() throws Exception {
+        String file = "test-jaspi.xml";
+        JaspiType rbac = loadRbac(file);
+        
+    }
+
+    private JaspiType loadRbac(String file) throws ParserConfigurationException, IOException, SAXException, JAXBException, XMLStreamException {
+        InputStream in = getClass().getClassLoader().getResourceAsStream(file);
+        Reader reader = new InputStreamReader(in);
+        JaspiType rbac = JaspiXmlUtil.loadJaspi(reader);
+        return rbac;
+    }
+
+
+
+}
diff --git a/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/providers/BadConstructorProvider.java b/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/providers/BadConstructorProvider.java
new file mode 100644
index 0000000..fbc54f5
--- /dev/null
+++ b/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/providers/BadConstructorProvider.java
@@ -0,0 +1,21 @@
+/**

+ * 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;

+

+public class BadConstructorProvider {

+

+}

diff --git a/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/providers/BadImplementProvider.java b/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/providers/BadImplementProvider.java
new file mode 100644
index 0000000..12db993
--- /dev/null
+++ b/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/providers/BadImplementProvider.java
@@ -0,0 +1,26 @@
+/**

+ * 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;

+

+public class BadImplementProvider {

+

+    public BadImplementProvider(Map props) {

+    }

+    

+}

diff --git a/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/providers/DummyProvider.java b/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/providers/DummyProvider.java
new file mode 100644
index 0000000..f01f748
--- /dev/null
+++ b/geronimo-jaspi/src/test/java/org/apache/geronimo/components/jaspi/providers/DummyProvider.java
@@ -0,0 +1,48 @@
+/**

+ * 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.callback.CallbackHandler;

+import javax.security.auth.message.AuthException;

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

+import javax.security.auth.message.config.ClientAuthConfig;

+import javax.security.auth.message.config.ServerAuthConfig;

+

+public class DummyProvider implements AuthConfigProvider {

+

+    public DummyProvider(Map props) {

+        

+    }

+    

+    public ClientAuthConfig getClientAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException, SecurityException {

+        // TODO Auto-generated method stub

+        return null;

+    }

+

+    public ServerAuthConfig getServerAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException, SecurityException {

+        // TODO Auto-generated method stub

+        return null;

+    }

+

+    public void refresh() throws AuthException, SecurityException {

+        // TODO Auto-generated method stub

+        

+    }

+

+}

diff --git a/geronimo-jaspi/src/test/resources/test-jaspi.xml b/geronimo-jaspi/src/test/resources/test-jaspi.xml
new file mode 100644
index 0000000..f22b07c
--- /dev/null
+++ b/geronimo-jaspi/src/test/resources/test-jaspi.xml
@@ -0,0 +1,30 @@
+<?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>
+        <className>org.apache.geronimo.components.jaspi.providers.DummyProvider</className>
+        <properties>foo=bar</properties>
+        <persistent>false</persistent>
+    </configProvider>
+
+</jaspi>
\ No newline at end of file