FELIX-3981 - Create a sample project for demonstrating Felix JAAS main features

Adding initial base skeleton comprising of couple of bundles. The app bundle exposes various servlets which demonstrates different ways of performing JAAS invocation

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1459644 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/examples/jaas/app/pom.xml b/examples/jaas/app/pom.xml
new file mode 100644
index 0000000..89aa747
--- /dev/null
+++ b/examples/jaas/app/pom.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix-parent</artifactId>
+    <version>2.1</version>
+    <relativePath>../../../pom/pom.xml</relativePath>
+  </parent>
+
+  <groupId>org.apache.felix.example</groupId>
+  <artifactId>org.apache.felix.example.jaas.app</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <name>JAAS Example - App Module</name>
+
+  <prerequisites>
+    <maven>3.0.3</maven>
+  </prerequisites>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>2.3.5</version>
+        <extensions>true</extensions>
+        <configuration>
+          <obrRepository>NONE</obrRepository>
+          <instructions>
+            <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+            <DynamicImport-Package>
+              org.apache.felix.jaas.boot
+            </DynamicImport-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-scr-plugin</artifactId>
+        <version>1.11.0</version>
+        <executions>
+          <execution>
+            <id>generate-scr-scrdescriptor</id>
+            <goals>
+              <goal>scr</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.6</source>
+          <target>1.6</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <version>4.2.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <version>4.2.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.scr.annotations</artifactId>
+      <version>1.9.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>2.4</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.jaas</artifactId>
+      <version>0.0.1-SNAPSHOT</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/examples/jaas/app/src/main/java/org/apache/felix/example/jaas/app/internal/BootClasspathDemoServlet.java b/examples/jaas/app/src/main/java/org/apache/felix/example/jaas/app/internal/BootClasspathDemoServlet.java
new file mode 100644
index 0000000..ef3bb8e
--- /dev/null
+++ b/examples/jaas/app/src/main/java/org/apache/felix/example/jaas/app/internal/BootClasspathDemoServlet.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.example.jaas.app.internal;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+
+@Component
+@Service(value = Servlet.class)
+@Property(name = "alias",value = "/jaas/boot")
+public class BootClasspathDemoServlet extends HttpServlet
+{
+
+    @Override
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException
+    {
+        //Demonstrates the JAAS authentication if the
+        // 1. Felix JAAS Boot support is used.
+        // 2. Global configuration policy is used - This needs to be enabled via
+        //      configuration of 'Apache Felix JAAS Configuration SPI'
+        //
+        //In that case client code does not have to
+        //manage Thread Context Classloader or provide explicit configuration
+
+        PrintWriter pw = resp.getWriter();
+        CallbackHandler handler = new ServletRequestCallbackHandler(req);
+
+        Subject subject = new Subject();
+        try
+        {
+            LoginContext lc = new LoginContext("sample", subject, handler);
+            lc.login();
+
+            pw.println("Principal authentication successful");
+            pw.println(subject);
+        }
+        catch (LoginException e)
+        {
+            handleAuthenticationFailure(e,pw);
+        }
+
+    }
+
+    private void handleAuthenticationFailure(LoginException e, PrintWriter pw)
+    {
+        pw.println("Authentication Failed");
+        pw.println(e);
+    }
+
+}
diff --git a/examples/jaas/app/src/main/java/org/apache/felix/example/jaas/app/internal/FactoryDemoServlet.java b/examples/jaas/app/src/main/java/org/apache/felix/example/jaas/app/internal/FactoryDemoServlet.java
new file mode 100644
index 0000000..851d5e7
--- /dev/null
+++ b/examples/jaas/app/src/main/java/org/apache/felix/example/jaas/app/internal/FactoryDemoServlet.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.example.jaas.app.internal;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.jaas.LoginContextFactory;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+
+@Component
+@Service(value = Servlet.class)
+@Property(name = "alias",value = "/jaas/factory")
+public class FactoryDemoServlet extends HttpServlet
+{
+    @Reference
+    private LoginContextFactory loginContextFactory;
+
+    @Override
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException
+    {
+
+        //Demonstrates the JAAS authentication if the
+        // 1. Felix JAAS LoginContextFactory is used.
+        //In that case client code does not have to
+        //manage Thread Context Classloader or provide explicit configuration
+
+        PrintWriter pw = resp.getWriter();
+        CallbackHandler handler = new ServletRequestCallbackHandler(req);
+        Subject subject = new Subject();
+        try
+        {
+            LoginContext lc = loginContextFactory.createLoginContext("sample",subject,handler);
+            lc.login();
+
+            pw.println("Principal authentication successful");
+            pw.println(subject);
+        }
+        catch (LoginException e)
+        {
+            handleAuthenticationFailure(e,pw);
+        }
+
+    }
+
+    private void handleAuthenticationFailure(LoginException e, PrintWriter pw)
+    {
+        pw.println("Authentication Failed");
+        pw.println(e);
+    }
+
+}
diff --git a/examples/jaas/app/src/main/java/org/apache/felix/example/jaas/app/internal/GlobalConfigDemoServlet.java b/examples/jaas/app/src/main/java/org/apache/felix/example/jaas/app/internal/GlobalConfigDemoServlet.java
new file mode 100644
index 0000000..ba874a4
--- /dev/null
+++ b/examples/jaas/app/src/main/java/org/apache/felix/example/jaas/app/internal/GlobalConfigDemoServlet.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.example.jaas.app.internal;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+
+@Component
+@Service(value = Servlet.class)
+@Property(name = "alias",value = "/jaas/global")
+public class GlobalConfigDemoServlet extends HttpServlet
+{
+
+    @Override
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException
+    {
+
+        //Demonstrates the JAAS authentication if the
+        // 1. Replace Global configuration policy is used
+        //
+        //This needs to be enabled via configuration of 'Apache Felix JAAS Configuration SPI'
+        //In that case client code does not have to provide explicit configuration
+
+        PrintWriter pw = resp.getWriter();
+        CallbackHandler handler = new ServletRequestCallbackHandler(req);
+
+        Subject subject = new Subject();
+        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        try
+        {
+            Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+            LoginContext lc = new LoginContext("sample", subject, handler);
+            lc.login();
+
+            pw.println("Principal authentication successful");
+            pw.println(subject);
+        }
+        catch (LoginException e)
+        {
+            handleAuthenticationFailure(e,pw);
+        }
+        finally
+        {
+            Thread.currentThread().setContextClassLoader(cl);
+        }
+    }
+
+    private void handleAuthenticationFailure(LoginException e, PrintWriter pw)
+    {
+        pw.println("Authentication Failed");
+        pw.println(e);
+    }
+
+}
diff --git a/examples/jaas/app/src/main/java/org/apache/felix/example/jaas/app/internal/ServletRequestCallbackHandler.java b/examples/jaas/app/src/main/java/org/apache/felix/example/jaas/app/internal/ServletRequestCallbackHandler.java
new file mode 100644
index 0000000..f7920f6
--- /dev/null
+++ b/examples/jaas/app/src/main/java/org/apache/felix/example/jaas/app/internal/ServletRequestCallbackHandler.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.example.jaas.app.internal;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.servlet.http.HttpServletRequest;
+
+public class ServletRequestCallbackHandler implements CallbackHandler
+{
+
+    private final HttpServletRequest request;
+
+    public ServletRequestCallbackHandler(HttpServletRequest request)
+    {
+        this.request = request;
+    }
+
+    @Override
+    public void handle(Callback[] callbacks) throws IOException,
+        UnsupportedCallbackException
+    {
+        for (Callback c : callbacks)
+        {
+            if (c instanceof NameCallback)
+            {
+                ((NameCallback) c).setName(getParam("j_username"));
+            }
+            if (c instanceof PasswordCallback)
+            {
+                ((PasswordCallback) c).setPassword(getParam("j_password").toCharArray());
+            }
+        }
+    }
+
+    private String getParam(String name)
+    {
+        String value = request.getParameter(name);
+        if (value == null)
+        {
+            throw new IllegalArgumentException("No parameter with name [" + name
+                + "] found");
+        }
+        return value.trim();
+    }
+}
diff --git a/examples/jaas/app/src/main/java/org/apache/felix/example/jaas/app/internal/TCCLDemoServlet.java b/examples/jaas/app/src/main/java/org/apache/felix/example/jaas/app/internal/TCCLDemoServlet.java
new file mode 100644
index 0000000..cb8c70f
--- /dev/null
+++ b/examples/jaas/app/src/main/java/org/apache/felix/example/jaas/app/internal/TCCLDemoServlet.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.example.jaas.app.internal;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+
+@Component
+@Service(value = Servlet.class)
+@Property(name = "alias",value = "/jaas/tccl")
+public class TCCLDemoServlet extends HttpServlet
+{
+
+    @Override
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException
+    {
+
+        //Demonstrates the JAAS authentication
+        //In following case the client code would have to
+        // 1. Manage the thread's context classloader
+        // 2. Add a DynamicImport for org.apache.felix.jaas.boot
+        // 3. Fetch the config using the Configuration.getInstance API and pass that on
+
+        PrintWriter pw = resp.getWriter();
+        CallbackHandler handler = new ServletRequestCallbackHandler(req);
+
+        Subject subject = new Subject();
+        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        try
+        {
+            Configuration config = Configuration.getInstance("JavaLoginConfig", null,
+                "FelixJaasProvider");
+            Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+            LoginContext lc = new LoginContext("sample", subject, handler, config);
+            lc.login();
+
+            pw.println("Principal authentication successful");
+            pw.println(subject);
+        }
+        catch (NoSuchAlgorithmException e)
+        {
+            throw new RuntimeException(e);
+        }
+        catch (NoSuchProviderException e)
+        {
+            throw new RuntimeException(e);
+        }
+        catch (LoginException e)
+        {
+            handleAuthenticationFailure(e,pw);
+        }
+        finally
+        {
+            Thread.currentThread().setContextClassLoader(cl);
+        }
+
+    }
+
+    private void handleAuthenticationFailure(LoginException e, PrintWriter pw)
+    {
+        pw.println("Authentication Failed");
+        pw.println(e);
+    }
+
+}
diff --git a/examples/jaas/lm-config/pom.xml b/examples/jaas/lm-config/pom.xml
new file mode 100644
index 0000000..80c2cb6
--- /dev/null
+++ b/examples/jaas/lm-config/pom.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix-parent</artifactId>
+    <version>2.1</version>
+    <relativePath>../../../pom/pom.xml</relativePath>
+  </parent>
+
+  <groupId>org.apache.felix.example</groupId>
+  <artifactId>org.apache.felix.example.jaas.lm-config</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <name>JAAS Example - Config based Login Module</name>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>2.3.5</version>
+        <extensions>true</extensions>
+        <configuration>
+          <obrRepository>NONE</obrRepository>
+          <instructions>
+            <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+            <Jaas-ModuleClass>org.apache.felix.example.jaas.config.internal.SampleConfigLoginModule</Jaas-ModuleClass>
+          </instructions>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>2.5.1</version>
+        <configuration>
+          <source>1.6</source>
+          <target>1.6</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+
+
+</project>
\ No newline at end of file
diff --git a/examples/jaas/lm-config/src/main/java/org/apache/felix/example/jaas/config/internal/SampleConfigLoginModule.java b/examples/jaas/lm-config/src/main/java/org/apache/felix/example/jaas/config/internal/SampleConfigLoginModule.java
new file mode 100644
index 0000000..79c9c08
--- /dev/null
+++ b/examples/jaas/lm-config/src/main/java/org/apache/felix/example/jaas/config/internal/SampleConfigLoginModule.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.example.jaas.config.internal;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+public class SampleConfigLoginModule implements LoginModule
+{
+    private Subject subject;
+    private CallbackHandler handler;
+    private Map<String, ?> options;
+    private Map<String, ?> sharedState;
+    private boolean succeeded;
+    private String name;
+
+    @Override
+    public void initialize(Subject subject, CallbackHandler callbackHandler,
+        Map<String, ?> sharedState, Map<String, ?> options)
+    {
+        this.subject = subject;
+        this.options = options;
+        this.handler = callbackHandler;
+        this.sharedState = sharedState;
+    }
+
+    @Override
+    public boolean login() throws LoginException
+    {
+        Callback[] callbacks = new Callback[2];
+        callbacks[0] = new NameCallback("Name");
+        callbacks[1] = new PasswordCallback("Password", false);
+
+        try
+        {
+            handler.handle(callbacks);
+        }
+        catch (IOException e)
+        {
+            throw new LoginException(e.getMessage());
+        }
+        catch (UnsupportedCallbackException e)
+        {
+            throw new LoginException(e.getMessage());
+        }
+
+        String name = ((NameCallback) callbacks[0]).getName();
+        char[] password = ((PasswordCallback) callbacks[1]).getPassword();
+
+        boolean result = Arrays.equals(name.toCharArray(), password);
+        succeeded = result;
+        this.name = name;
+        return result;
+    }
+
+    @Override
+    public boolean commit() throws LoginException
+    {
+        if (succeeded)
+        {
+            subject.getPrincipals().add(new SamplePrincipal(name, "SampleConfigLoginModule"));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean abort() throws LoginException
+    {
+       return true;
+    }
+
+    @Override
+    public boolean logout() throws LoginException
+    {
+        return false;
+    }
+}
diff --git a/examples/jaas/lm-config/src/main/java/org/apache/felix/example/jaas/config/internal/SamplePrincipal.java b/examples/jaas/lm-config/src/main/java/org/apache/felix/example/jaas/config/internal/SamplePrincipal.java
new file mode 100644
index 0000000..5932362
--- /dev/null
+++ b/examples/jaas/lm-config/src/main/java/org/apache/felix/example/jaas/config/internal/SamplePrincipal.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.example.jaas.config.internal;
+
+import java.security.Principal;
+
+public class SamplePrincipal implements Principal
+{
+    private final String name;
+    private final String prefix;
+
+    public SamplePrincipal(String name, String prefix)
+    {
+        this.name = name;
+        this.prefix = prefix;
+    }
+
+    @Override
+    public String getName()
+    {
+        return name;
+    }
+
+    @Override
+    public boolean equals(Object o)
+    {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        SamplePrincipal that = (SamplePrincipal) o;
+
+        if (!name.equals(that.name))
+            return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return name.hashCode();
+    }
+
+    @Override
+    public String toString()
+    {
+        return prefix + ":" + name;
+    }
+}
diff --git a/examples/jaas/pom.xml b/examples/jaas/pom.xml
new file mode 100644
index 0000000..ed8e323
--- /dev/null
+++ b/examples/jaas/pom.xml
@@ -0,0 +1,39 @@
+<!-- 
+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. 
+-->
+<project>
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix-parent</artifactId>
+    <version>2.1</version>
+    <relativePath>../../pom/pom.xml</relativePath>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <packaging>pom</packaging>
+  <name>Apache Felix Examples: JAAS</name>
+  <groupId>org.apache.felix.example</groupId>
+  <artifactId>jaas-reactor</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+
+
+  <modules>
+      <module>lm-config</module>
+      <module>app</module>
+  </modules>
+
+</project>