You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@archiva.apache.org by ol...@apache.org on 2012/04/06 11:59:32 UTC

svn commit: r1310268 [41/42] - in /archiva/redback/redback-core/trunk: ./ redback-authentication/ redback-authentication/redback-authentication-api/ redback-authentication/redback-authentication-api/src/ redback-authentication/redback-authentication-ap...

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/ctl/LdapController.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/ctl/LdapController.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/ctl/LdapControllerException.java
URL: http://svn.apache.org/viewvc/archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/ctl/LdapControllerException.java?rev=1310268&view=auto
==============================================================================
--- archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/ctl/LdapControllerException.java (added)
+++ archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/ctl/LdapControllerException.java Fri Apr  6 09:58:14 2012
@@ -0,0 +1,33 @@
+package org.codehaus.plexus.redback.users.ldap.ctl;
+
+/*
+ * Copyright 2001-2007 The Codehaus.
+ *
+ * Licensed 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.
+ */
+
+public class LdapControllerException
+    extends Exception
+{
+
+    public LdapControllerException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+
+    public LdapControllerException( String message )
+    {
+        super( message );
+    }
+
+}

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/ctl/LdapControllerException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/ctl/LdapControllerException.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/service/DefaultLdapCacheService.java
URL: http://svn.apache.org/viewvc/archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/service/DefaultLdapCacheService.java?rev=1310268&view=auto
==============================================================================
--- archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/service/DefaultLdapCacheService.java (added)
+++ archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/service/DefaultLdapCacheService.java Fri Apr  6 09:58:14 2012
@@ -0,0 +1,118 @@
+package org.codehaus.plexus.redback.users.ldap.service;
+
+/*
+ * Copyright 2011 The Codehaus.
+ *
+ * Licensed 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.
+ */
+
+import org.codehaus.plexus.cache.builder.CacheBuilder;
+import org.codehaus.plexus.redback.common.ldap.LdapUser;
+import org.springframework.stereotype.Service;
+
+import javax.inject.Inject;
+
+/**
+ * DefaultLdapCacheService
+ *
+ * @author: Maria Odea Ching <oc...@apache.org>
+ * @version
+ */
+@Service
+public class DefaultLdapCacheService
+    implements LdapCacheService
+{
+    @Inject
+    private CacheBuilder cacheBuilder;
+
+    // LDAP Users
+
+    /**
+     * @see LdapCacheService#getUser(String)
+     */
+    public LdapUser getUser( String username )
+    {
+        return (LdapUser) cacheBuilder.getCache( "ldapUser" ).get( username );
+    }
+
+    /**
+     * @see LdapCacheService#removeUser(String)
+     */
+    public boolean removeUser( String username )
+    {
+        return ( cacheBuilder.getCache( "ldapUser" ).remove( username ) == null ? false : true );
+    }
+
+    /**
+     * @see LdapCacheService#removeAllUsers()
+     */
+    public void removeAllUsers()
+    {
+        cacheBuilder.getCache( "ldapUser" ).clear();
+    }
+
+    /**
+     * @see LdapCacheService#addUser(org.codehaus.plexus.redback.common.ldap.LdapUser)
+     */
+    public void addUser( LdapUser user )
+    {
+        LdapUser existingUser = (LdapUser) cacheBuilder.getCache( "ldapUser" ).get( user.getUsername() );
+        if( existingUser != null )
+        {
+            removeUser( user.getUsername() );
+        }
+
+        cacheBuilder.getCache( "ldapUser" ).put( user.getUsername(), user );
+    }
+
+    // LDAP UserDn
+
+    /**
+     * @see LdapCacheService#getLdapUserDn(String)
+     */
+    public String getLdapUserDn( String username )
+    {
+        return (String) cacheBuilder.getCache( "ldapUserDn" ).get( username );
+    }
+
+    /**
+     * @see LdapCacheService#removeLdapUserDn(String)
+     */
+    public boolean removeLdapUserDn( String username )
+    {
+        return ( cacheBuilder.getCache( "ldapUserDn" ).remove( username ) == null ? false : true );
+    }
+
+    /**
+     * @see org.codehaus.plexus.redback.users.ldap.service.LdapCacheService#removeAllLdapUserDn()
+     */
+    public void removeAllLdapUserDn()
+    {
+        cacheBuilder.getCache( "ldapUserDn" ).clear();
+    }
+
+    /**
+     * @see LdapCacheService#addLdapUserDn(String, String) 
+     */
+    public void addLdapUserDn( String username, String userDn )
+    {
+        String existingUserDn = (String) cacheBuilder.getCache( "ldapUserDn" ).get( username );
+        if( existingUserDn != null )
+        {
+            removeUser( username );
+        }
+
+        cacheBuilder.getCache( "ldapUserDn" ).put( username, userDn );    
+    }
+    
+}

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/service/DefaultLdapCacheService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/service/DefaultLdapCacheService.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/service/LdapCacheService.java
URL: http://svn.apache.org/viewvc/archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/service/LdapCacheService.java?rev=1310268&view=auto
==============================================================================
--- archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/service/LdapCacheService.java (added)
+++ archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/service/LdapCacheService.java Fri Apr  6 09:58:14 2012
@@ -0,0 +1,90 @@
+package org.codehaus.plexus.redback.users.ldap.service;
+
+/*
+ * Copyright 2011 The Codehaus.
+ *
+ * Licensed 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.
+ */
+
+import org.codehaus.plexus.redback.common.ldap.LdapUser;
+
+/**
+ * LdapCacheService
+ *
+ * Service that manages the LDAP caches: LDAP connections and LDAP users
+ *
+ * @author: Maria Odea Ching <oc...@apache.org>
+ * @version
+ */
+public interface LdapCacheService
+{
+    /**
+     * Retrieve LDAP user with the given username from the cache.
+     * Returns null if user is not found.
+     *
+     * @param username
+     * @return
+     */
+    LdapUser getUser( String username );
+
+    /**
+     * Remove LDAP user with the given username from the cache.
+     * Returns the removed object if it was in the cache. Otherwise, returns null.
+     * 
+     * @param username
+     * @return
+     */
+    boolean removeUser( String username );
+
+    /**
+     * Remove all LDAP users in the cache. In short, it flushes the cache.
+     *
+     */
+    void removeAllUsers();
+
+    /**
+     * Adds the user to the LDAP users cache.
+     *
+     * @param user
+     */
+    void addUser( LdapUser user );
+
+    /**
+     * Retrieve the cached LDAP userDn for the given user.
+     *
+     * @param username
+     * @return
+     */
+    String getLdapUserDn( String username );
+
+    /**
+     * Remove the cached LDAP userDn for the given user.
+     *
+     * @param username
+     * @return
+     */
+    boolean removeLdapUserDn( String username );
+
+    /**
+     * Remove all cached LDAP userDn
+     */
+    void removeAllLdapUserDn();
+
+    /**
+     * All the LDAP userDn for the given user to the cache
+     *
+     * @param username
+     * @param userDn
+     */
+    void addLdapUserDn( String username, String userDn );
+}

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/service/LdapCacheService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/java/org/codehaus/plexus/redback/users/ldap/service/LdapCacheService.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/resources/META-INF/spring-context.xml
URL: http://svn.apache.org/viewvc/archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/resources/META-INF/spring-context.xml?rev=1310268&view=auto
==============================================================================
--- archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/resources/META-INF/spring-context.xml (added)
+++ archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/resources/META-INF/spring-context.xml Fri Apr  6 09:58:14 2012
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+           http://www.springframework.org/schema/context 
+           http://www.springframework.org/schema/context/spring-context-3.0.xsd"
+       default-lazy-init="true">
+
+  <context:annotation-config />
+  <context:component-scan 
+    base-package="org.codehaus.plexus.redback.users.ldap"/>
+
+  <!-- REDBACK-289/MRM-1488 -->
+  <!-- Cache for LDAP users. Data is refreshed every 3 mins. -->
+  <bean name="cache#ldapUser" class="org.codehaus.plexus.cache.ehcache.EhcacheCache">
+    <property name="diskExpiryThreadIntervalSeconds" value="180"/>
+    <property name="diskPersistent" value="false"/>
+    <property name="eternal" value="false"/>
+    <property name="maxElementsInMemory"  value="1000"/>
+    <property name="memoryEvictionPolicy" value="LRU"/>
+    <property name="name" value="ldapUsersCache"/>
+    <property name="overflowToDisk" value="false"/>
+    <property name="timeToIdleSeconds" value="90"/>
+    <property name="timeToLiveSeconds" value="180"/>
+  </bean>
+
+  <!-- Cache for users' LDAP userDn. Data is refreshed every 3 mins. -->
+  <bean name="cache#ldapUserDn" class="org.codehaus.plexus.cache.ehcache.EhcacheCache">
+    <property name="diskExpiryThreadIntervalSeconds" value="180"/>
+    <property name="diskPersistent" value="false"/>
+    <property name="eternal" value="false"/>
+    <property name="maxElementsInMemory"  value="1000"/>
+    <property name="memoryEvictionPolicy" value="LRU"/>
+    <property name="name" value="ldapUserDnCache"/>
+    <property name="overflowToDisk" value="false"/>
+    <property name="timeToIdleSeconds" value="90"/>
+    <property name="timeToLiveSeconds" value="180"/>
+  </bean>
+
+</beans>
\ No newline at end of file

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/resources/META-INF/spring-context.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/main/resources/META-INF/spring-context.xml
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/java/org/codehaus/plexus/redback/users/ldap/LdapUserManagerTest.java
URL: http://svn.apache.org/viewvc/archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/java/org/codehaus/plexus/redback/users/ldap/LdapUserManagerTest.java?rev=1310268&view=auto
==============================================================================
--- archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/java/org/codehaus/plexus/redback/users/ldap/LdapUserManagerTest.java (added)
+++ archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/java/org/codehaus/plexus/redback/users/ldap/LdapUserManagerTest.java Fri Apr  6 09:58:14 2012
@@ -0,0 +1,337 @@
+package org.codehaus.plexus.redback.users.ldap;
+
+/*
+ * Copyright 2001-2006 The Codehaus.
+ *
+ * Licensed 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.
+ */
+
+import junit.framework.TestCase;
+import org.codehaus.plexus.redback.common.ldap.connection.LdapConnection;
+import org.codehaus.plexus.redback.common.ldap.connection.LdapConnectionFactory;
+import org.codehaus.plexus.redback.policy.PasswordEncoder;
+import org.codehaus.plexus.redback.policy.encoders.SHA1PasswordEncoder;
+import org.codehaus.plexus.redback.users.User;
+import org.codehaus.plexus.redback.users.UserManager;
+import org.codehaus.plexus.redback.users.UserNotFoundException;
+import org.codehaus.plexus.redback.users.ldap.service.LdapCacheService;
+import org.codehaus.redback.components.apacheds.ApacheDs;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import java.util.List;
+
+
+/**
+ * LdapUserManagerTest 
+ *
+ * @author <a href="mailto:jesse@codehaus.org">Jesse McConnell</a>
+ * @version $Id$
+ */  
+
+@RunWith( SpringJUnit4ClassRunner.class )
+@ContextConfiguration( locations = { "classpath*:/META-INF/spring-context.xml", "classpath*:/spring-context.xml" } )
+public class LdapUserManagerTest
+    extends TestCase
+{
+    
+    protected Logger log = LoggerFactory.getLogger( getClass() );
+
+    @Inject
+    @Named(value = "userManager#ldap")
+    private UserManager userManager;
+
+    @Inject
+    @Named( value = "apacheDS#test" )
+    private ApacheDs apacheDs;
+
+    private String suffix;
+
+    private PasswordEncoder passwordEncoder;
+
+    @Inject
+    @Named(value = "ldapConnectionFactory#configurable")
+    private LdapConnectionFactory connectionFactory;
+
+    @Inject
+    private LdapCacheService ldapCacheService;
+
+    public void testFoo()
+        throws Exception
+    {
+
+    }
+
+    @Before
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        passwordEncoder = new SHA1PasswordEncoder();
+
+        suffix = apacheDs.addSimplePartition( "test", new String[] { "redback", "plexus", "codehaus", "org" } )
+            .getSuffix();
+
+        log.info( "DN Suffix: " + suffix );
+
+        apacheDs.startServer();
+        
+        clearManyUsers();
+
+        makeUsers();
+
+    }
+
+    @After
+    public void tearDown()
+        throws Exception
+    {
+        // clear cache
+        ldapCacheService.removeAllUsers();
+
+        InitialDirContext context = apacheDs.getAdminContext();
+
+        context.unbind( createDn( "jesse" ) );
+
+        context.unbind( createDn( "joakim" ) );
+
+        apacheDs.stopServer();
+
+        super.tearDown();
+    }
+
+    private void makeUsers()
+        throws Exception
+    {
+        InitialDirContext context = apacheDs.getAdminContext();
+
+        String cn = "jesse";
+        bindUserObject( context, cn, createDn( cn ) );
+        assertExist( context, createDn( cn ), "cn", cn );
+
+        cn = "joakim";
+        bindUserObject( context, cn, createDn( cn ) );
+        assertExist( context, createDn( cn ), "cn", cn );
+
+    }
+
+    @Test
+    public void testConnection()
+        throws Exception
+    {
+        assertNotNull( connectionFactory );
+
+        LdapConnection connection = null; 
+        try
+        {
+        connection = connectionFactory.getConnection();
+
+        assertNotNull( connection );
+
+        DirContext context = connection.getDirContext();
+
+        assertNotNull( context );
+        } finally {
+            connection.close();
+        }
+    }
+
+    @Test
+    public void testDirectUsersExistence()
+        throws Exception
+    {
+        LdapConnection connection = null; 
+        try
+        {
+        connection = connectionFactory.getConnection();
+
+        DirContext context = connection.getDirContext();
+
+        assertExist( context, createDn( "jesse" ), "cn", "jesse" );
+        assertExist( context, createDn( "joakim" ), "cn", "joakim" );
+        } finally {
+            connection.close();
+        }
+        
+    }
+
+    @Test
+    public void testUserManager()
+        throws Exception
+    {
+        assertNotNull( userManager );
+
+        //assertNull( ldapCacheService.getUser( "jesse" ) );
+
+        assertTrue( userManager.userExists( "jesse" ) );
+
+        //assertNotNull( ldapCacheService.getUser( "jesse" ) );
+
+        List<User> users = userManager.getUsers();
+
+        assertNotNull( users );
+
+        assertEquals( 2, users.size() );
+
+        User jesse = userManager.findUser( "jesse" );
+
+        assertNotNull( jesse );
+
+        assertEquals( "jesse", jesse.getPrincipal().toString() );
+        assertEquals( "jesse@apache.org", jesse.getEmail() );
+        assertEquals( "foo", jesse.getFullName() );
+        System.out.println( "=====>"+jesse.getEncodedPassword());
+        System.out.println( "=====>"+passwordEncoder.encodePassword( "foo" ));
+        assertTrue( passwordEncoder.isPasswordValid( jesse.getEncodedPassword(), "foo" ) );
+
+    }
+
+    @Test
+    public void testUserNotFoundException()
+        throws Exception
+    {
+        try
+        {
+            userManager.findUser( "foo bar" );
+            fail( "not a UserNotFoundException with an unknown user" );
+        }
+        catch ( UserNotFoundException e )
+        {
+            // cool it works !
+        }
+    }
+
+    @Test
+    public void testWithManyUsers()
+        throws Exception
+    {
+        makeManyUsers();
+        
+        assertNotNull( userManager );
+
+        assertTrue( userManager.userExists( "user10" ) );
+
+        List<User> users = userManager.getUsers();
+
+        assertNotNull( users );
+
+        assertEquals( 10002, users.size() );
+
+        User user10 = userManager.findUser( "user10" );
+
+        assertNotNull( user10 );
+    }
+    
+    private void makeManyUsers()
+        throws Exception
+    {
+        InitialDirContext context = apacheDs.getAdminContext();
+        
+        for ( int i = 0 ; i < 10000 ; i++ )
+        {    
+            String cn = "user"+i;
+            bindUserObject( context, cn, createDn( cn ) );
+        }
+    
+    }
+    
+    private void clearManyUsers()
+        throws Exception
+    {
+        InitialDirContext context = apacheDs.getAdminContext();
+        
+        for ( int i = 0 ; i < 10000 ; i++ )
+        {    
+            String cn = "user"+i;
+            try
+            {
+                context.unbind( createDn( cn ) );
+            }
+            catch ( NamingException e )
+            {
+                // OK lets try with next one
+            }
+        }
+    
+    }
+    
+    private void bindUserObject( DirContext context, String cn, String dn )
+        throws Exception
+    {
+        Attributes attributes = new BasicAttributes( true );
+        BasicAttribute objectClass = new BasicAttribute( "objectClass" );
+        objectClass.add( "top" );
+        objectClass.add( "inetOrgPerson" );
+        objectClass.add( "person" );
+        objectClass.add( "organizationalperson" );
+        attributes.put( objectClass );
+        attributes.put( "cn", cn );
+        attributes.put( "sn", "foo" );
+        attributes.put( "mail", cn+"@apache.org" );
+        attributes.put( "userPassword", passwordEncoder.encodePassword( "foo" ) );
+        attributes.put( "givenName", "foo" );
+        context.createSubcontext( dn, attributes );
+    }
+
+    private String createDn( String cn )
+    {
+        return "cn=" + cn + "," + suffix;
+    }
+
+    private void assertExist( DirContext context, String dn, String attribute, String value )
+        throws NamingException
+    {
+        SearchControls ctls = new SearchControls();
+
+        ctls.setDerefLinkFlag( true );
+        ctls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
+        ctls.setReturningAttributes( new String[] { "*" } );
+
+        BasicAttributes matchingAttributes = new BasicAttributes();
+        matchingAttributes.put( attribute, value );
+        BasicAttribute objectClass = new BasicAttribute( "objectClass" );
+        objectClass.add( "inetOrgPerson" );
+        matchingAttributes.put( objectClass );
+
+        NamingEnumeration<SearchResult> results = context.search( suffix, matchingAttributes );
+        // NamingEnumeration<SearchResult> results = context.search( suffix, "(" + attribute + "=" + value + ")", ctls
+        // );
+
+        assertTrue( results.hasMoreElements() );
+        SearchResult result = results.nextElement();
+        Attributes attrs = result.getAttributes();
+        Attribute testAttr = attrs.get( attribute );
+        assertEquals( value, testAttr.get() );
+
+    }
+
+}

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/java/org/codehaus/plexus/redback/users/ldap/LdapUserManagerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/java/org/codehaus/plexus/redback/users/ldap/LdapUserManagerTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/java/org/codehaus/plexus/redback/users/ldap/service/LdapCacheServiceTest.java
URL: http://svn.apache.org/viewvc/archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/java/org/codehaus/plexus/redback/users/ldap/service/LdapCacheServiceTest.java?rev=1310268&view=auto
==============================================================================
--- archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/java/org/codehaus/plexus/redback/users/ldap/service/LdapCacheServiceTest.java (added)
+++ archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/java/org/codehaus/plexus/redback/users/ldap/service/LdapCacheServiceTest.java Fri Apr  6 09:58:14 2012
@@ -0,0 +1,108 @@
+package org.codehaus.plexus.redback.users.ldap.service;
+
+/*
+ * Copyright 2011 The Codehaus.
+ *
+ * Licensed 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.
+ */
+
+import junit.framework.TestCase;
+import org.codehaus.plexus.redback.common.ldap.LdapUser;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import javax.inject.Inject;
+
+/**
+ * @author: Maria Odea Ching <oc...@apache.org>
+ * @version
+ */
+@RunWith( SpringJUnit4ClassRunner.class )
+@ContextConfiguration( locations = { "classpath*:/META-INF/spring-context.xml", "classpath*:/spring-context.xml" } )
+public class LdapCacheServiceTest
+    extends TestCase
+{
+    @Inject
+    private LdapCacheService ldapCacheService;
+
+    private static final String USERNAME = "dummy";
+
+    @After
+    public void tearDown()
+        throws Exception
+    {
+        ldapCacheService.removeAllUsers();
+        ldapCacheService.removeAllLdapUserDn();
+
+        super.tearDown();
+    }
+
+    @Test
+    public void testLdapUserDnCache()
+        throws Exception
+    {
+        ldapCacheService.addLdapUserDn( USERNAME, "userDn" );
+
+        assertNotNull( ldapCacheService.getLdapUserDn( USERNAME ) );
+
+        ldapCacheService.removeLdapUserDn( USERNAME );
+
+        assertNull( ldapCacheService.getLdapUserDn( USERNAME ) );
+    }
+
+    @Test
+    public void testClearLdapUserDnCache()
+        throws Exception
+    {
+        ldapCacheService.addLdapUserDn( USERNAME, "userDn" );
+
+        assertNotNull( ldapCacheService.getLdapUserDn( USERNAME ) );
+
+        ldapCacheService.removeLdapUserDn( USERNAME );
+
+        assertNull( ldapCacheService.getLdapUserDn( USERNAME ) );
+    }
+
+    @Test
+    public void testLdapUsersCache()
+        throws Exception
+    {
+        LdapUser ldapUser = new LdapUser( USERNAME );
+
+        ldapCacheService.addUser( ldapUser );
+
+        assertNotNull( ldapCacheService.getUser( USERNAME ) );
+
+        ldapCacheService.removeUser( USERNAME );
+
+        assertNull( ldapCacheService.getUser( USERNAME ) );
+    }
+
+    @Test
+    public void testClearLdapUsersCache()
+        throws Exception
+    {
+        LdapUser ldapUser = new LdapUser( USERNAME );
+
+        ldapCacheService.addUser( ldapUser );
+
+        assertNotNull( ldapCacheService.getUser( USERNAME ) );
+
+        ldapCacheService.removeAllUsers();
+
+        assertNull( ldapCacheService.getUser( USERNAME ) );
+    }
+}

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/java/org/codehaus/plexus/redback/users/ldap/service/LdapCacheServiceTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/java/org/codehaus/plexus/redback/users/ldap/service/LdapCacheServiceTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/resources/org/codehaus/plexus/redback/users/ldap/users.ldif
URL: http://svn.apache.org/viewvc/archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/resources/org/codehaus/plexus/redback/users/ldap/users.ldif?rev=1310268&view=auto
==============================================================================
--- archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/resources/org/codehaus/plexus/redback/users/ldap/users.ldif (added)
+++ archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/resources/org/codehaus/plexus/redback/users/ldap/users.ldif Fri Apr  6 09:58:14 2012
@@ -0,0 +1,21 @@
+dn: dc=redback,dc=plexus,dc=codehaus,dc=org
+cn: jesse
+givenName: foo
+userPassword: C+7Hteo/D9vJXQ3UfzxbwnXaijM=
+objectClass: top
+objectClass: inetorgperson
+objectClass: person
+objectClass: organizationalperson
+email: foo
+sn: foo
+
+dn: dc=redback,dc=plexus,dc=codehaus,dc=org
+cn: joakim
+givenName: foo
+userPassword: C+7Hteo/D9vJXQ3UfzxbwnXaijM=
+objectClass: top
+objectClass: inetorgperson
+objectClass: person
+objectClass: organizationalperson
+email: foo
+sn: foo

Added: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/resources/spring-context.xml
URL: http://svn.apache.org/viewvc/archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/resources/spring-context.xml?rev=1310268&view=auto
==============================================================================
--- archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/resources/spring-context.xml (added)
+++ archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/resources/spring-context.xml Fri Apr  6 09:58:14 2012
@@ -0,0 +1,59 @@
+<?xml version="1.0"?>
+
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+           http://www.springframework.org/schema/context 
+           http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+  <context:property-placeholder system-properties-mode="OVERRIDE"/>
+
+  <bean name="apacheDS#test" class="org.codehaus.redback.components.apacheds.DefaultApacheDs"
+      scope="prototype">
+    <property name="basedir" value="${basedir}/target/apacheds"/>
+    <property name="port" value="${ldapPort}"/>
+    <property name="enableNetworking" value="true"/>
+    <property name="password" value="secret"/>
+  </bean>
+
+  <bean name="ldapConnectionFactory#configurable" class="org.codehaus.plexus.redback.common.ldap.connection.ConfigurableLdapConnectionFactory">
+    <property name="hostname" value="localhost"/>
+    <property name="port" value="${ldapPort}"/>
+    <property name="baseDn" value="dc=redback,dc=plexus,dc=codehaus,dc=org"/>
+    <property name="contextFactory" value="com.sun.jndi.ldap.LdapCtxFactory"/>
+    <property name="password" value="secret"/>
+    <property name="bindDn" value="uid=admin,ou=system"/>
+    <property name="userConf" ref="userConfiguration"/>
+  </bean>
+
+  <bean name="userMapper#ldap" class="org.codehaus.plexus.redback.common.ldap.LdapUserMapper">
+    <property name="emailAttribute" value="mail"/>
+    <property name="fullNameAttribute" value="givenName"/>
+    <property name="passwordAttribute" value="userPassword"/>
+    <property name="userIdAttribute" value="cn"/>
+    <property name="userBaseDn" value="dc=redback,dc=plexus,dc=codehaus,dc=org"/>
+    <property name="userObjectClass" value="inetOrgPerson"/>
+    <property name="userConf" ref="userConfiguration"/>
+  </bean>
+
+</beans>
\ No newline at end of file

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/resources/spring-context.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-ldap/src/test/resources/spring-context.xml
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/pom.xml
URL: http://svn.apache.org/viewvc/archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/pom.xml?rev=1310268&view=auto
==============================================================================
--- archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/pom.xml (added)
+++ archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/pom.xml Fri Apr  6 09:58:14 2012
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2006 The Codehaus.
+  ~ 
+  ~ Licensed 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 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/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.codehaus.redback</groupId>
+    <artifactId>redback-users-providers</artifactId>
+    <version>1.5-SNAPSHOT</version>
+  </parent>
+  <artifactId>redback-users-memory</artifactId>
+  <name>Redback :: Users Provider :: Memory</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-policy</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context-support</artifactId>
+    </dependency>   
+    <dependency>
+      <groupId>javax.annotation</groupId>
+      <artifactId>jsr250-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-users-tests</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/pom.xml
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/MemoryUserManager.java
URL: http://svn.apache.org/viewvc/archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/MemoryUserManager.java?rev=1310268&view=auto
==============================================================================
--- archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/MemoryUserManager.java (added)
+++ archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/MemoryUserManager.java Fri Apr  6 09:58:14 2012
@@ -0,0 +1,332 @@
+package org.codehaus.plexus.redback.users.memory;
+
+/*
+ * Copyright 2001-2006 The Apache Software Foundation.
+ *
+ * Licensed 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.
+ */
+
+import org.codehaus.plexus.redback.policy.UserSecurityPolicy;
+import org.codehaus.plexus.redback.users.AbstractUserManager;
+import org.codehaus.plexus.redback.users.PermanentUserException;
+import org.codehaus.plexus.redback.users.User;
+import org.codehaus.plexus.redback.users.UserQuery;
+import org.codehaus.plexus.redback.users.UserManager;
+import org.codehaus.plexus.redback.users.UserNotFoundException;
+import org.codehaus.plexus.redback.users.memory.util.UserSorter;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.annotation.Resource;
+
+/**
+ * @version $Id$
+ */
+@Service("userManager#memory")
+public class MemoryUserManager
+    extends AbstractUserManager
+    implements UserManager
+{
+    @Resource
+    private UserSecurityPolicy userSecurityPolicy;
+
+    public String getId()
+    {
+        Properties props = new Properties();
+        URL url = this
+            .getClass()
+            .getResource(
+                "META-INF/maven/org/codehaus/plexus/redback/redback-users-memory/pom.properties" );
+
+        if ( url != null )
+        {
+            try
+            {
+                props.load( url.openStream() );
+                return "MemoryUserManager - " + props.getProperty( "version" );
+            }
+            catch ( IOException e )
+            {
+                // Fall thru
+            }
+        }
+        return "MemoryUserManager - (unknown version)";
+    }
+    
+    public boolean isReadOnly()
+    {
+        return false;
+    }
+
+    public UserQuery createUserQuery()
+    {
+        return new SimpleUserQuery();
+    }
+
+    public List<User> findUsersByQuery( UserQuery query )
+    {
+        SimpleUserQuery uq = (SimpleUserQuery) query;
+
+        List<User> list = new ArrayList<User>();
+
+        for ( Iterator<User> i = users.values().iterator(); i.hasNext(); )
+        {
+            SimpleUser user = (SimpleUser) i.next();
+            boolean matches = uq.matches( user );
+            if ( matches )
+            {
+                list.add( user );
+            }
+        }
+
+        Collections.sort( list, uq.getComparator() );
+
+        List<User> cutList = new ArrayList<User>();
+
+        for ( long i = query.getFirstResult();
+              i < list.size() && ( query.getMaxResults() == -1 || i < query.getFirstResult() + uq.getMaxResults() );
+              i++ )
+        {
+            cutList.add( list.get( (int) i ) );
+        }
+        return cutList;
+    }
+
+    private Map<Object, User> users = new HashMap<Object, User>();
+
+    public User addUser( User user )
+    {
+        saveUser( user );
+        fireUserManagerUserAdded( user );
+
+        // If there exists no encoded password, then this is a new user setup 
+        if ( StringUtils.isEmpty( user.getEncodedPassword() ) )
+        {
+            userSecurityPolicy.extensionChangePassword( user );
+        }
+
+        return user;
+    }
+
+    private void saveUser( User user )
+    {
+        triggerInit();
+        users.put( user.getPrincipal(), user );
+    }
+
+    public User updateUser( User user )
+    {
+        return updateUser( user, false );
+    }
+
+    public User updateUser( User user, boolean passwordChangeRequired )
+    {
+        if ( StringUtils.isNotEmpty( user.getPassword() ) )
+        {
+            userSecurityPolicy.extensionChangePassword( user, passwordChangeRequired );
+        }
+
+        saveUser( user );
+
+        fireUserManagerUserUpdated( user );
+
+        return user;
+    }
+
+    public User findUser( Object principal )
+        throws UserNotFoundException
+    {
+        triggerInit();
+        User user = users.get( principal );
+
+        if ( user == null )
+        {
+            throw new UserNotFoundException( "Cannot find the user with the principal '" + principal + "'." );
+        }
+
+        return user;
+    }
+
+    public boolean userExists( Object principal )
+    {
+        try
+        {
+            findUser( principal );
+            return true;
+        }
+        catch ( UserNotFoundException ne )
+        {
+            return false;
+        }
+    }
+
+    public void deleteUser( Object principal )
+        throws UserNotFoundException
+    {
+        deleteUser( principal.toString() );
+    }
+
+    public User createUser( String username, String fullName, String emailAddress )
+    {
+        User user = new SimpleUser();
+        user.setUsername( username );
+        user.setFullName( fullName );
+        user.setEmail( emailAddress );
+
+        return user;
+    }
+
+    public void deleteUser( String username )
+        throws UserNotFoundException
+    {
+        User user = findUser( username );
+
+        if ( user.isPermanent() )
+        {
+            throw new PermanentUserException( "Cannot delete permanent user." );
+        }
+
+        users.remove( user.getPrincipal() );
+
+        fireUserManagerUserRemoved( user );
+    }
+
+    public void addUserUnchecked( User user )
+    {
+        addUser( user );
+    }
+
+    public void eraseDatabase()
+    {
+        users.clear();
+    }
+
+    public User findUser( String username )
+        throws UserNotFoundException
+    {
+        triggerInit();
+        User user = null;
+
+        Iterator<User> it = users.values().iterator();
+        while ( it.hasNext() )
+        {
+            User u = it.next();
+            if ( u.getUsername().equals( username ) )
+            {
+                user = u;
+            }
+        }
+
+        if ( user == null )
+        {
+            throw new UserNotFoundException( "Unable to find user '" + username + "'" );
+        }
+
+        return user;
+    }
+
+    public List<User> findUsersByUsernameKey( String usernameKey, boolean orderAscending )
+    {
+        triggerInit();
+
+        List<User> userList = new ArrayList<User>();
+
+        Iterator<User> it = users.values().iterator();
+        while ( it.hasNext() )
+        {
+            User u = it.next();
+            if ( u.getUsername().indexOf( usernameKey ) > -1 )
+            {
+                userList.add( u );
+            }
+        }
+
+        Collections.sort( userList, new UserSorter( orderAscending ) );
+
+        return userList;
+    }
+
+    public List<User> findUsersByFullNameKey( String fullNameKey, boolean orderAscending )
+    {
+        triggerInit();
+
+        List<User> userList = new ArrayList<User>();
+
+        Iterator<User> it = users.values().iterator();
+        while ( it.hasNext() )
+        {
+            User u = it.next();
+            if ( u.getFullName().indexOf( fullNameKey ) > -1 )
+            {
+                userList.add( u );
+            }
+        }
+
+        Collections.sort( userList, new UserSorter( orderAscending ) );
+
+        return userList;
+    }
+
+    public List<User> findUsersByEmailKey( String emailKey, boolean orderAscending )
+    {
+        triggerInit();
+
+        List<User> userList = new ArrayList<User>();
+
+        Iterator<User> it = users.values().iterator();
+        while ( it.hasNext() )
+        {
+            User u = it.next();
+            if ( u.getEmail().indexOf( emailKey ) > -1 )
+            {
+                userList.add( u );
+            }
+        }
+
+        Collections.sort( userList, new UserSorter( orderAscending ) );
+
+        return userList;
+    }
+
+    public List<User> getUsers()
+    {
+        triggerInit();
+        return new ArrayList<User>( users.values() );
+    }
+
+    public List<User> getUsers( boolean ascendingUsername )
+    {
+        return getUsers();
+    }
+
+    private boolean hasTriggeredInit = false;
+
+    public void triggerInit()
+    {
+        if ( !hasTriggeredInit )
+        {
+            fireUserManagerInit( users.isEmpty() );
+            hasTriggeredInit = true;
+        }
+    }
+}

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/MemoryUserManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/MemoryUserManager.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/SimpleUser.java
URL: http://svn.apache.org/viewvc/archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/SimpleUser.java?rev=1310268&view=auto
==============================================================================
--- archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/SimpleUser.java (added)
+++ archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/SimpleUser.java Fri Apr  6 09:58:14 2012
@@ -0,0 +1,220 @@
+package org.codehaus.plexus.redback.users.memory;
+
+/*
+ * Copyright 2001-2006 The Codehaus.
+ *
+ * Licensed 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.
+ */
+
+import org.codehaus.plexus.redback.users.User;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * A Simple User record.
+ *
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ */
+public class SimpleUser
+    implements User, Serializable
+{
+    private String username;
+
+    private String password;
+
+    private String email;
+
+    private String fullName;
+
+    private String encodedPassword;
+
+    private Date lastPasswordChange;
+
+    private Date lastLoginDate;
+
+    private int countFailedLoginAttempts = 0;
+
+    private boolean locked = false;
+
+    private boolean permanent = false;
+
+    private boolean validated = false;
+
+    private List<String> previousEncodedPasswords;
+
+    private Date accountCreationDate;
+
+    private boolean passwordChangeRequired;
+
+    public SimpleUser()
+    {
+        // no op
+    }
+
+    public void addPreviousEncodedPassword( String encodedPassword )
+    {
+        getPreviousEncodedPasswords().add( encodedPassword );
+    }
+
+    public Date getAccountCreationDate()
+    {
+        return accountCreationDate;
+    }
+
+    public int getCountFailedLoginAttempts()
+    {
+        return countFailedLoginAttempts;
+    }
+
+    public String getEmail()
+    {
+        return email;
+    }
+
+    public String getEncodedPassword()
+    {
+        return encodedPassword;
+    }
+
+    public String getFullName()
+    {
+        return fullName;
+    }
+
+    public Date getLastLoginDate()
+    {
+        return lastLoginDate;
+    }
+
+    public Date getLastPasswordChange()
+    {
+        return lastPasswordChange;
+    }
+
+    public String getPassword()
+    {
+        return password;
+    }
+
+    public List<String> getPreviousEncodedPasswords()
+    {
+        if ( previousEncodedPasswords == null )
+        {
+            previousEncodedPasswords = new ArrayList<String>();
+        }
+        return previousEncodedPasswords;
+    }
+
+    public Object getPrincipal()
+    {
+        return username;
+    }
+
+    public String getUsername()
+    {
+        return username;
+    }
+
+    public boolean isLocked()
+    {
+        return locked;
+    }
+
+    public void setAccountCreationDate( Date accountCreationDate )
+    {
+        this.accountCreationDate = accountCreationDate;
+    }
+
+    public void setCountFailedLoginAttempts( int countFailedLoginAttempts )
+    {
+        this.countFailedLoginAttempts = countFailedLoginAttempts;
+    }
+
+    public void setEmail( String email )
+    {
+        this.email = email;
+    }
+
+    public void setEncodedPassword( String encodedPassword )
+    {
+        this.encodedPassword = encodedPassword;
+    }
+
+    public void setFullName( String fullName )
+    {
+        this.fullName = fullName;
+    }
+
+    public void setLastLoginDate( Date lastLoginDate )
+    {
+        this.lastLoginDate = lastLoginDate;
+    }
+
+    public void setLastPasswordChange( Date lastPasswordChange )
+    {
+        this.lastPasswordChange = lastPasswordChange;
+    }
+
+    public void setLocked( boolean locked )
+    {
+        this.locked = locked;
+    }
+
+    public void setPassword( String password )
+    {
+        this.password = password;
+    }
+
+    public void setPreviousEncodedPasswords( List<String> previousEncodedPasswords )
+    {
+        this.previousEncodedPasswords = previousEncodedPasswords;
+    }
+
+    public void setUsername( String username )
+    {
+        this.username = username;
+    }
+
+    public boolean isPasswordChangeRequired()
+    {
+        return passwordChangeRequired;
+    }
+
+    public void setPasswordChangeRequired( boolean passwordChangeRequired )
+    {
+        this.passwordChangeRequired = passwordChangeRequired;
+    }
+
+    public boolean isPermanent()
+    {
+        return permanent;
+    }
+
+    public void setPermanent( boolean permanent )
+    {
+        this.permanent = permanent;
+    }
+
+    public boolean isValidated()
+    {
+        return validated;
+    }
+
+    public void setValidated( boolean validated )
+    {
+        this.validated = validated;
+    }
+}

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/SimpleUser.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/SimpleUser.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/SimpleUserQuery.java
URL: http://svn.apache.org/viewvc/archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/SimpleUserQuery.java?rev=1310268&view=auto
==============================================================================
--- archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/SimpleUserQuery.java (added)
+++ archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/SimpleUserQuery.java Fri Apr  6 09:58:14 2012
@@ -0,0 +1,91 @@
+package org.codehaus.plexus.redback.users.memory;
+
+/*
+ * Copyright 2001-2006 The Apache Software Foundation.
+ *
+ * Licensed 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.
+ */
+
+import org.codehaus.plexus.redback.users.AbstractUserQuery;
+import org.codehaus.plexus.redback.users.User;
+
+import java.util.Comparator;
+
+public class SimpleUserQuery
+    extends AbstractUserQuery
+{
+
+    /**
+     * Returns true if this user should be considered a match of the current query
+     *
+     * @param user
+     * @return
+     */
+    public boolean matches( User user )
+    {
+        if ( getUsername() != null && user.getUsername() != null &&
+            user.getUsername().toLowerCase().indexOf( getUsername().toLowerCase() ) == -1 )
+        {
+            return false;
+        }
+        else if ( getFullName() != null && user.getFullName() != null &&
+            user.getFullName().toLowerCase().indexOf( getFullName().toLowerCase() ) == -1 )
+        {
+            return false;
+        }
+        else if ( getEmail() != null && user.getEmail() != null &&
+            user.getEmail().toLowerCase().indexOf( getEmail().toLowerCase() ) == -1 )
+        {
+            return false;
+        }
+        else
+        {
+            return true;
+        }
+
+    }
+
+    /**
+     * Returns a comparator used for sorting a collection of User objects based on the ordering set
+     * on this UserQuery's {@link #setOrderBy(String)} and {@link #setAscending(boolean)}. 
+     * @return
+     */
+    public Comparator<User> getComparator()
+    {
+        return new Comparator<User>()
+        {
+            public int compare( User user1, User user2 )
+            {
+                return ( isAscending() ? 1 : -1 ) * compareUsers( user1, user2 );
+            }
+        };
+    }
+
+    private int compareUsers( User user, User user1 )
+    {
+        if ( ORDER_BY_EMAIL.equals( getOrderBy() ) )
+        {
+            return user.getEmail() == null ? -1
+                : user1.getEmail() == null ? 1 : user.getEmail().compareTo( user1.getEmail() );
+        }
+        else if ( ORDER_BY_FULLNAME.equals( getOrderBy() ) )
+        {
+            return user.getFullName() == null ? -1
+                : user1.getFullName() == null ? 1 : user.getFullName().compareTo( user1.getFullName() );
+        }
+        else
+        {
+            return user.getUsername().compareTo( user1.getUsername() );
+        }
+    }
+}

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/SimpleUserQuery.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/SimpleUserQuery.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/util/UserSorter.java
URL: http://svn.apache.org/viewvc/archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/util/UserSorter.java?rev=1310268&view=auto
==============================================================================
--- archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/util/UserSorter.java (added)
+++ archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/util/UserSorter.java Fri Apr  6 09:58:14 2012
@@ -0,0 +1,69 @@
+package org.codehaus.plexus.redback.users.memory.util;
+
+import org.codehaus.plexus.redback.users.User;
+
+import java.util.Comparator;
+
+/**
+ * UserSorter
+ */
+public class UserSorter
+    implements Comparator<User>
+{
+    private boolean ascending;
+
+    public UserSorter()
+    {
+        this.ascending = true;
+    }
+
+    public UserSorter( boolean ascending )
+    {
+        this.ascending = ascending;
+    }
+
+    public int compare( User o1, User o2 )
+    {
+        if ( ( o1 == null ) && ( o2 == null ) )
+        {
+            return 0;
+        }
+
+        if ( ( o1 == null ) && ( o2 != null ) )
+        {
+            return -1;
+        }
+
+        if ( ( o1 != null ) && ( o2 != null ) )
+        {
+            return 1;
+        }
+
+        User u1 = null;
+        User u2 = null;
+
+        if ( isAscending() )
+        {
+            u1 = o1;
+            u2 = o2;
+        }
+        else
+        {
+            u1 = o2;
+            u2 = o1;
+        }
+
+        return u1.getUsername().compareTo( u2.getUsername() );
+    }
+
+    public boolean isAscending()
+    {
+        return ascending;
+    }
+
+    public void setAscending( boolean ascending )
+    {
+        this.ascending = ascending;
+    }
+
+}

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/util/UserSorter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/java/org/codehaus/plexus/redback/users/memory/util/UserSorter.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/resources/META-INF/spring-context.xml
URL: http://svn.apache.org/viewvc/archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/resources/META-INF/spring-context.xml?rev=1310268&view=auto
==============================================================================
--- archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/resources/META-INF/spring-context.xml (added)
+++ archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/resources/META-INF/spring-context.xml Fri Apr  6 09:58:14 2012
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+           http://www.springframework.org/schema/context 
+           http://www.springframework.org/schema/context/spring-context-3.0.xsd"
+       default-lazy-init="true">
+
+  <context:annotation-config />
+  <context:component-scan base-package="org.codehaus.plexus.redback.users.memory"/>
+ 
+</beans>
\ No newline at end of file

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/resources/META-INF/spring-context.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/main/resources/META-INF/spring-context.xml
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/test/java/org/codehaus/plexus/redback/users/MemoryUserManagerTest.java
URL: http://svn.apache.org/viewvc/archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/test/java/org/codehaus/plexus/redback/users/MemoryUserManagerTest.java?rev=1310268&view=auto
==============================================================================
--- archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/test/java/org/codehaus/plexus/redback/users/MemoryUserManagerTest.java (added)
+++ archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/test/java/org/codehaus/plexus/redback/users/MemoryUserManagerTest.java Fri Apr  6 09:58:14 2012
@@ -0,0 +1,45 @@
+package org.codehaus.plexus.redback.users;
+
+/*
+ * Copyright 2005 The Codehaus.
+ *
+ * Licensed 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.
+ */
+
+import org.codehaus.plexus.redback.users.memory.MemoryUserManager;
+import org.codehaus.plexus.redback.users.provider.test.AbstractUserManagerTestCase;
+import org.junit.Before;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/**
+ * {@link MemoryUserManager} test:
+ * 
+ * @author <a href='mailto:rahul.thakur.xdev@gmail.com'>Rahul Thakur</a>
+ */
+public class MemoryUserManagerTest
+    extends AbstractUserManagerTestCase
+{
+
+    @Inject @Named(value = "userManager#memory")
+    UserManager userManager;
+
+    @Before
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        setUserManager( userManager );
+    }
+}

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/test/java/org/codehaus/plexus/redback/users/MemoryUserManagerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-providers/redback-users-memory/src/test/java/org/codehaus/plexus/redback/users/MemoryUserManagerTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: archiva/redback/redback-core/trunk/redback-users/redback-users-tests/pom.xml
URL: http://svn.apache.org/viewvc/archiva/redback/redback-core/trunk/redback-users/redback-users-tests/pom.xml?rev=1310268&view=auto
==============================================================================
--- archiva/redback/redback-core/trunk/redback-users/redback-users-tests/pom.xml (added)
+++ archiva/redback/redback-core/trunk/redback-users/redback-users-tests/pom.xml Fri Apr  6 09:58:14 2012
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2006 The Codehaus.
+  ~ 
+  ~ Licensed 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 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/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.codehaus.redback</groupId>
+    <artifactId>redback-users</artifactId>
+    <version>1.5-SNAPSHOT</version>
+  </parent>
+  <artifactId>redback-users-tests</artifactId>
+  <name>Redback :: User Tests</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.codehaus.redback</groupId>
+      <artifactId>redback-policy</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context-support</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-test</artifactId>
+    </dependency>
+  </dependencies>
+
+</project>

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-tests/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: archiva/redback/redback-core/trunk/redback-users/redback-users-tests/pom.xml
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision