directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From elecha...@apache.org
Subject svn commit: r1187013 [8/12] - in /directory/apacheds/branches/apacheds-txns: ./ all/ apache-felix/ apache-felix/bundle/ apache-felix/src/ apache-felix/src/main/ apache-felix/src/main/resources/ core-annotations/ core-annotations/src/main/java/org/apach...
Date Thu, 20 Oct 2011 19:42:13 GMT
Added: directory/apacheds/branches/apacheds-txns/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/PasswordUtil.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/PasswordUtil.java?rev=1187013&view=auto
==============================================================================
--- directory/apacheds/branches/apacheds-txns/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/PasswordUtil.java (added)
+++ directory/apacheds/branches/apacheds-txns/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/PasswordUtil.java Thu Oct 20 19:41:49 2011
@@ -0,0 +1,550 @@
+/*
+ *   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.directory.server.core.authn;
+
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.directory.server.core.api.authn.ppolicy.PasswordPolicyConfiguration;
+import org.apache.directory.shared.ldap.model.constants.LdapSecurityConstants;
+import org.apache.directory.shared.ldap.model.entry.Attribute;
+import org.apache.directory.shared.ldap.model.entry.Value;
+import org.apache.directory.shared.util.Base64;
+import org.apache.directory.shared.util.DateUtils;
+import org.apache.directory.shared.util.Strings;
+import org.apache.directory.shared.util.UnixCrypt;
+
+
+/**
+ * A utility class containing methods related to processing passwords.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PasswordUtil
+{
+
+    /** The SHA1 hash length */
+    public static final int SHA1_LENGTH = 20;
+
+    /** The SHA256 hash length */
+    public static final int SHA256_LENGTH = 32;
+
+    /** The SHA384 hash length */
+    public static final int SHA384_LENGTH = 48;
+
+    /** The SHA512 hash length */
+    public static final int SHA512_LENGTH = 64;
+
+    /** The MD5 hash length */
+    public static final int MD5_LENGTH = 16;
+
+
+    /**
+     * Get the algorithm from the stored password. 
+     * It can be found on the beginning of the stored password, between 
+     * curly brackets.
+     * @param credentials the credentials of the user
+     * @return the name of the algorithm to use
+     */
+    public static LdapSecurityConstants findAlgorithm( byte[] credentials )
+    {
+        if ( ( credentials == null ) || ( credentials.length == 0 ) )
+        {
+            return null;
+        }
+
+        if ( credentials[0] == '{' )
+        {
+            // get the algorithm
+            int pos = 1;
+
+            while ( pos < credentials.length )
+            {
+                if ( credentials[pos] == '}' )
+                {
+                    break;
+                }
+
+                pos++;
+            }
+
+            if ( pos < credentials.length )
+            {
+                if ( pos == 1 )
+                {
+                    // We don't have an algorithm : return the credentials as is
+                    return null;
+                }
+
+                String algorithm = Strings.toLowerCase( new String( credentials, 1, pos - 1 ) );
+
+                return LdapSecurityConstants.getAlgorithm( algorithm );
+            }
+            else
+            {
+                // We don't have an algorithm
+                return null;
+            }
+        }
+        else
+        {
+            // No '{algo}' part
+            return null;
+        }
+    }
+
+
+    /**
+     * @see #createStoragePassword(byte[], LdapSecurityConstants)
+     */
+    public static byte[] createStoragePassword( String credentials, LdapSecurityConstants algorithm )
+    {
+        return createStoragePassword( Strings.getBytesUtf8(credentials), algorithm );
+    }
+    
+    
+    /**
+     * create a hashed password in a format that can be stored in the server.
+     * If the specified algorithm requires a salt then a random salt of 8 byte size is used
+     *  
+     * @param credentials the plain text password
+     * @param algorithm the hashing algorithm to be applied
+     * @return the password after hashing with the given algorithm 
+     */
+    public static byte[] createStoragePassword( byte[] credentials, LdapSecurityConstants algorithm )
+    {
+        byte[] salt;
+        
+        switch( algorithm )
+        {
+            case HASH_METHOD_SSHA:
+            case HASH_METHOD_SSHA256:
+            case HASH_METHOD_SSHA384:
+            case HASH_METHOD_SSHA512:
+            case HASH_METHOD_SMD5:
+                salt = new byte[8]; // we use 8 byte salt always except for "crypt" which needs 2 byte salt
+                new SecureRandom().nextBytes( salt );
+                break;
+                
+            case HASH_METHOD_CRYPT:
+                salt = new byte[2];
+                SecureRandom sr = new SecureRandom();
+                int i1 = sr.nextInt( 64 );
+                int i2 = sr.nextInt( 64 );
+                
+                salt[0] = ( byte ) ( i1 < 12 ? ( i1 + '.' ) : i1 < 38 ? ( i1 + 'A' - 12 ) : ( i1 + 'a' - 38 ) );
+                salt[1] = ( byte ) ( i2 < 12 ? ( i2 + '.' ) : i2 < 38 ? ( i2 + 'A' - 12 ) : ( i2 + 'a' - 38 ) );
+                break;
+                
+            default:
+                salt = null;
+        }
+        
+        byte[] hashedPassword = encryptPassword( credentials, algorithm, salt );
+        StringBuffer sb = new StringBuffer();
+
+        if ( algorithm != null )
+        {
+            sb.append( '{' ).append( algorithm.getName().toUpperCase() ).append( '}' );
+
+            if ( algorithm == LdapSecurityConstants.HASH_METHOD_CRYPT )
+            {
+                sb.append( Strings.utf8ToString(salt) );
+                sb.append( Strings.utf8ToString(hashedPassword) );
+            }
+            else if ( salt != null )
+            {
+                byte[] hashedPasswordWithSaltBytes = new byte[hashedPassword.length + salt.length];
+                merge( hashedPasswordWithSaltBytes, hashedPassword, salt );
+                sb.append( String.valueOf( Base64.encode( hashedPasswordWithSaltBytes ) ) );
+            }
+            else
+            {
+                sb.append( String.valueOf( Base64.encode(hashedPassword) ) );
+            }
+        }
+        else
+        {
+            sb.append( Strings.utf8ToString(hashedPassword) );
+        }
+        
+        return Strings.getBytesUtf8(sb.toString());
+    }
+    
+
+    /**
+     * 
+     * Compare the credentials.
+     * We have at least 6 algorithms to encrypt the password :
+     * <ul>
+     * <li>- SHA</li>
+     * <li>- SSHA (salted SHA)</li>
+     * <li>- SHA-2(256, 384 and 512 and their salted versions)</li>
+     * <li>- MD5</li>
+     * <li>- SMD5 (slated MD5)</li>
+     * <li>- crypt (unix crypt)</li>
+     * <li>- plain text, ie no encryption.</li>
+     * </ul>
+     * <p>
+     *  If we get an encrypted password, it is prefixed by the used algorithm, between
+     *  brackets : {SSHA}password ...
+     *  </p>
+     *  If the password is using SSHA, SMD5 or crypt, some 'salt' is added to the password :
+     *  <ul>
+     *  <li>- length(password) - 20, starting at 21th position for SSHA</li>
+     *  <li>- length(password) - 16, starting at 16th position for SMD5</li>
+     *  <li>- length(password) - 2, starting at 3rd position for crypt</li>
+     *  </ul>
+     *  <p>
+     *  For (S)SHA, SHA-256 and (S)MD5, we have to transform the password from Base64 encoded text
+     *  to a byte[] before comparing the password with the stored one.
+     *  </p>
+     *  <p>
+     *  For crypt, we only have to remove the salt.
+     *  </p>
+     *  <p>
+     *  At the end, we use the digest() method for (S)SHA and (S)MD5, the crypt() method for
+     *  the CRYPT algorithm and a straight comparison for PLAIN TEXT passwords.
+     *  </p>
+     *  <p>
+     *  The stored password is always using the unsalted form, and is stored as a bytes array.
+     *  </p>
+     *
+     * @param receivedCredentials the credentials provided by user
+     * @param storedCredentials the credentials stored in the server
+     * @return true if they are equal, false otherwise
+     */
+    public static boolean compareCredentials( byte[] receivedCredentials, byte[] storedCredentials )
+    {
+        LdapSecurityConstants algorithm = findAlgorithm( storedCredentials );
+        
+        if ( algorithm != null )
+        {
+            EncryptionMethod encryptionMethod = new EncryptionMethod( algorithm, null );
+            
+            // Let's get the encrypted part of the stored password
+            // We should just keep the password, excluding the algorithm
+            // and the salt, if any.
+            // But we should also get the algorithm and salt to
+            // be able to encrypt the submitted user password in the next step
+            byte[] encryptedStored = PasswordUtil.splitCredentials( storedCredentials, encryptionMethod );
+            
+            // Reuse the saltedPassword informations to construct the encrypted
+            // password given by the user.
+            byte[] userPassword = PasswordUtil.encryptPassword( receivedCredentials, encryptionMethod.getAlgorithm(), encryptionMethod.getSalt() );
+            
+            // Now, compare the two passwords.
+            return Arrays.equals( userPassword, encryptedStored );
+        }
+        else
+        {
+            return Arrays.equals( storedCredentials, receivedCredentials );
+        }
+    }
+    
+
+    /**
+     * encrypts the given credentials based on the algorithm name and optional salt
+     *
+     * @param credentials the credentials to be encrypted
+     * @param algorithm the algorithm to be used for encrypting the credentials
+     * @param salt value to be used as salt (optional)
+     * @return the encrypted credentials
+     */
+    public static byte[] encryptPassword( byte[] credentials, LdapSecurityConstants algorithm, byte[] salt )
+    {
+        switch ( algorithm )
+        {
+            case HASH_METHOD_SHA:
+            case HASH_METHOD_SSHA:
+                return digest( LdapSecurityConstants.HASH_METHOD_SHA, credentials, salt );
+
+            case HASH_METHOD_SHA256:
+            case HASH_METHOD_SSHA256:
+                return digest( LdapSecurityConstants.HASH_METHOD_SHA256, credentials, salt );
+
+            case HASH_METHOD_SHA384:
+            case HASH_METHOD_SSHA384:
+                return digest( LdapSecurityConstants.HASH_METHOD_SHA384, credentials, salt );
+
+            case HASH_METHOD_SHA512:
+            case HASH_METHOD_SSHA512:
+                return digest( LdapSecurityConstants.HASH_METHOD_SHA512, credentials, salt );
+
+            case HASH_METHOD_MD5:
+            case HASH_METHOD_SMD5:
+                return digest( LdapSecurityConstants.HASH_METHOD_MD5, credentials, salt );
+
+            case HASH_METHOD_CRYPT:
+                String saltWithCrypted = UnixCrypt.crypt( Strings.utf8ToString(credentials), Strings
+                    .utf8ToString(salt) );
+                String crypted = saltWithCrypted.substring( 2 );
+
+                return Strings.getBytesUtf8(crypted);
+
+            default:
+                return credentials;
+        }
+    }
+
+
+    /**
+     * Compute the hashed password given an algorithm, the credentials and 
+     * an optional salt.
+     *
+     * @param algorithm the algorithm to use
+     * @param password the credentials
+     * @param salt the optional salt
+     * @return the digested credentials
+     */
+    private static byte[] digest( LdapSecurityConstants algorithm, byte[] password, byte[] salt )
+    {
+        MessageDigest digest;
+
+        try
+        {
+            digest = MessageDigest.getInstance( algorithm.getName() );
+        }
+        catch ( NoSuchAlgorithmException e1 )
+        {
+            return null;
+        }
+
+        if ( salt != null )
+        {
+            digest.update( password );
+            digest.update( salt );
+            return digest.digest();
+        }
+        else
+        {
+            return digest.digest( password );
+        }
+    }
+
+
+    /**
+     * Decompose the stored password in an algorithm, an eventual salt
+     * and the password itself.
+     *
+     * If the algorithm is SHA, SSHA, MD5 or SMD5, the part following the algorithm
+     * is base64 encoded
+     *
+     * @param encryptionMethod The structure to feed
+     * @return The password
+     * @param credentials the credentials to split
+     */
+    public static byte[] splitCredentials( byte[] credentials, EncryptionMethod encryptionMethod )
+    {
+        int algoLength = encryptionMethod.getAlgorithm().getName().length() + 2;
+
+        int hashLen = 0;
+        
+        switch ( encryptionMethod.getAlgorithm() )
+        {
+            case HASH_METHOD_MD5:
+            case HASH_METHOD_SHA:
+                try
+                {
+                    // We just have the password just after the algorithm, base64 encoded.
+                    // Just decode the password and return it.
+                    return Base64
+                        .decode( new String( credentials, algoLength, credentials.length - algoLength, "UTF-8" )
+                            .toCharArray() );
+                }
+                catch ( UnsupportedEncodingException uee )
+                {
+                    // do nothing
+                    return credentials;
+                }
+
+            case HASH_METHOD_SMD5:
+                try
+                {
+                    // The password is associated with a salt. Decompose it
+                    // in two parts, after having decoded the password.
+                    // The salt will be stored into the EncryptionMethod structure
+                    // The salt is at the end of the credentials, and is 8 bytes long
+                    byte[] passwordAndSalt = Base64.decode( new String( credentials, algoLength, credentials.length
+                        - algoLength, "UTF-8" ).toCharArray() );
+
+                    int saltLength = passwordAndSalt.length - MD5_LENGTH;
+                    encryptionMethod.setSalt( new byte[saltLength] );
+                    byte[] password = new byte[MD5_LENGTH];
+                    split( passwordAndSalt, 0, password, encryptionMethod.getSalt() );
+
+                    return password;
+                }
+                catch ( UnsupportedEncodingException uee )
+                {
+                    // do nothing
+                    return credentials;
+                }
+
+            case HASH_METHOD_SSHA:
+                hashLen = SHA1_LENGTH;
+            
+            case HASH_METHOD_SHA256:
+            case HASH_METHOD_SSHA256:
+                if ( hashLen == 0 )
+                {
+                    hashLen = SHA256_LENGTH;
+                }
+            
+            case HASH_METHOD_SHA384:
+            case HASH_METHOD_SSHA384:
+                if ( hashLen == 0 )
+                {
+                    hashLen = SHA384_LENGTH;
+                }
+                
+            case HASH_METHOD_SHA512:
+            case HASH_METHOD_SSHA512:
+                if ( hashLen == 0 )
+                {
+                    hashLen = SHA512_LENGTH;
+                }
+                
+                try
+                {
+                    // The password is associated with a salt. Decompose it
+                    // in two parts, after having decoded the password.
+                    // The salt will be stored into the EncryptionMethod structure
+                    // The salt is at the end of the credentials, and is 8 bytes long
+                    byte[] passwordAndSalt = Base64.decode( new String( credentials, algoLength, credentials.length
+                        - algoLength, "UTF-8" ).toCharArray() );
+
+                    int saltLength = passwordAndSalt.length - hashLen;
+                    encryptionMethod.setSalt( new byte[saltLength] );
+                    byte[] password = new byte[hashLen];
+                    split( passwordAndSalt, 0, password, encryptionMethod.getSalt() );
+
+                    return password;
+                }
+                catch ( UnsupportedEncodingException uee )
+                {
+                    // do nothing
+                    return credentials;
+                }
+
+            case HASH_METHOD_CRYPT:
+                // The password is associated with a salt. Decompose it
+                // in two parts, storing the salt into the EncryptionMethod structure.
+                // The salt comes first, not like for SSHA and SMD5, and is 2 bytes long
+                encryptionMethod.setSalt( new byte[2] );
+                byte[] password = new byte[credentials.length - encryptionMethod.getSalt().length - algoLength];
+                split( credentials, algoLength, encryptionMethod.getSalt(), password );
+
+                return password;
+
+            default:
+                // unknown method
+                return credentials;
+
+        }
+    }
+
+
+    private static void split( byte[] all, int offset, byte[] left, byte[] right )
+    {
+        System.arraycopy( all, offset, left, 0, left.length );
+        System.arraycopy( all, offset + left.length, right, 0, right.length );
+    }
+
+
+    private static void merge( byte[] all, byte[] left, byte[] right )
+    {
+        System.arraycopy( left, 0, all, 0, left.length );
+        System.arraycopy( right, 0, all, left.length, right.length );
+    }
+
+
+    /**
+     * checks if the given password's change time is older than the max age 
+     *
+     * @param pwdChangedZtime time when the password was last changed
+     * @param pwdMaxAgeSec the max age value in seconds
+     * @return true if expired, false otherwise
+     */
+    public static boolean isPwdExpired( String pwdChangedZtime, int pwdMaxAgeSec )
+    {
+        Date pwdChangeDate = DateUtils.getDate( pwdChangedZtime );
+
+        long time = pwdMaxAgeSec * 1000;
+        time += pwdChangeDate.getTime();
+
+        Date expiryDate = DateUtils.getDate( DateUtils.getGeneralizedTime( time ) );
+        Date now = DateUtils.getDate( DateUtils.getGeneralizedTime() );
+
+        boolean expired = false;
+
+        if ( expiryDate.equals( now ) || expiryDate.before( now ) )
+        {
+            expired = true;
+        }
+
+        return expired;
+    }
+
+
+    /**
+     * purges failure timestamps which are older than the configured interval
+     * (section 7.6 in the draft)
+     */
+    public static void purgeFailureTimes( PasswordPolicyConfiguration config, Attribute pwdFailTimeAt )
+    {
+        long interval = config.getPwdFailureCountInterval();
+
+        if ( interval == 0 )
+        {
+            return;
+        }
+
+        interval *= 1000;
+
+        long currentTime = DateUtils.getDate( DateUtils.getGeneralizedTime() ).getTime();
+        List<Value<?>> valList = new ArrayList<Value<?>>();
+
+        for ( Value<?> value : pwdFailTimeAt )
+        {
+            String failureTime = value.getString();
+            long time = DateUtils.getDate( failureTime ).getTime();
+            time += interval;
+
+            if ( currentTime > time )
+            {
+                valList.add( value );
+            }
+        }
+
+        for ( Value<?> val : valList )
+        {
+            pwdFailTimeAt.remove( val );
+        }
+    }
+}

Added: directory/apacheds/branches/apacheds-txns/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/SimpleAuthenticator.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/SimpleAuthenticator.java?rev=1187013&view=auto
==============================================================================
--- directory/apacheds/branches/apacheds-txns/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/SimpleAuthenticator.java (added)
+++ directory/apacheds/branches/apacheds-txns/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/SimpleAuthenticator.java Thu Oct 20 19:41:49 2011
@@ -0,0 +1,417 @@
+/*
+ *  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.directory.server.core.authn;
+
+
+import java.net.SocketAddress;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.naming.Context;
+
+import org.apache.commons.collections.map.LRUMap;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.directory.server.core.api.LdapPrincipal;
+import org.apache.directory.server.core.api.entry.ClonedServerEntry;
+import org.apache.directory.server.core.api.interceptor.context.BindOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
+import org.apache.directory.server.i18n.I18n;
+import org.apache.directory.shared.ldap.model.constants.AuthenticationLevel;
+import org.apache.directory.shared.ldap.model.constants.LdapSecurityConstants;
+import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.model.entry.Attribute;
+import org.apache.directory.shared.ldap.model.entry.Entry;
+import org.apache.directory.shared.ldap.model.entry.Value;
+import org.apache.directory.shared.ldap.model.exception.LdapAuthenticationException;
+import org.apache.directory.shared.ldap.model.exception.LdapException;
+import org.apache.directory.shared.ldap.model.name.Dn;
+import org.apache.directory.shared.util.Base64;
+import org.apache.directory.shared.util.StringConstants;
+import org.apache.directory.shared.util.Strings;
+import org.apache.directory.shared.util.UnixCrypt;
+import org.apache.mina.core.session.IoSession;
+
+
+/**
+ * A simple {@link Authenticator} that authenticates clear text passwords
+ * contained within the <code>userPassword</code> attribute in DIT. If the
+ * password is stored with a one-way encryption applied (e.g. SHA), the password
+ * is hashed the same way before comparison.
+ *
+ * We use a cache to speedup authentication, where the Dn/password are stored.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SimpleAuthenticator extends AbstractAuthenticator
+{
+    /** A speedup for logger in debug mode */
+    private static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+    /**
+     * A cache to store passwords. It's a speedup, we will be able to avoid backend lookups.
+     *
+     * Note that the backend also use a cache mechanism, but for performance gain, it's good
+     * to manage a cache here. The main problem is that when a user modify his password, we will
+     * have to update it at three different places :
+     * - in the backend,
+     * - in the partition cache,
+     * - in this cache.
+     *
+     * The update of the backend and partition cache is already correctly handled, so we will
+     * just have to offer an access to refresh the local cache.
+     *
+     * We need to be sure that frequently used passwords be always in cache, and not discarded.
+     * We will use a LRU cache for this purpose.
+     */
+    private final LRUMap credentialCache;
+
+    /** Declare a default for this cache. 100 entries seems to be enough */
+    private static final int DEFAULT_CACHE_SIZE = 100;
+
+    /**
+     * Define the interceptors we should *not* go through when we will have to request the backend
+     * about a userPassword.
+     */
+    private static final Collection<String> USERLOOKUP_BYPASS;
+
+    static
+    {
+        Set<String> c = new HashSet<String>();
+        c.add( "NormalizationInterceptor" );
+        c.add( "AuthenticationInterceptor" );
+        c.add( "AciAuthorizationInterceptor" );
+        c.add( "DefaultAuthorizationInterceptor" );
+        c.add( "AdministrativePointInterceptor" );
+        c.add( "ExceptionInterceptor" );
+        c.add( "OperationalAttributeInterceptor" );
+        c.add( "SchemaInterceptor" );
+        c.add( "CollectiveAttributeInterceptor" );
+        c.add( "SubentryInterceptor" );
+        c.add( "EventInterceptor" );
+        c.add( "TriggerInterceptor" );
+        USERLOOKUP_BYPASS = Collections.unmodifiableCollection( c );
+    }
+
+
+    /**
+     * Creates a new instance.
+     * @see AbstractAuthenticator
+     */
+    public SimpleAuthenticator()
+    {
+        super( AuthenticationLevel.SIMPLE );
+        credentialCache = new LRUMap( DEFAULT_CACHE_SIZE );
+    }
+
+
+    /**
+     * Creates a new instance, with an initial cache size
+     * @param cacheSize the size of the credential cache
+     */
+    public SimpleAuthenticator( int cacheSize )
+    {
+        super( AuthenticationLevel.SIMPLE );
+
+        credentialCache = new LRUMap( cacheSize > 0 ? cacheSize : DEFAULT_CACHE_SIZE );
+    }
+
+
+    /**
+     * Get the password either from cache or from backend.
+     * @param principalDN The Dn from which we want the password
+     * @return A byte array which can be empty if the password was not found
+     * @throws Exception If we have a problem during the lookup operation
+     */
+    private LdapPrincipal getStoredPassword( BindOperationContext bindContext ) throws LdapException
+    {
+        LdapPrincipal principal = null;
+
+        // use cache only if pwdpolicy is not enabled
+        if( !getDirectoryService().isPwdPolicyEnabled() )
+        {
+            synchronized ( credentialCache )
+            {
+                principal = ( LdapPrincipal ) credentialCache.get( bindContext.getDn().getNormName() );
+            }
+        }
+
+        byte[] storedPassword;
+
+        if ( principal == null )
+        {
+            // Not found in the cache
+            // Get the user password from the backend
+            storedPassword = lookupUserPassword( bindContext );
+
+            // Deal with the special case where the user didn't enter a password
+            // We will compare the empty array with the credentials. Sometime,
+            // a user does not set a password. This is bad, but there is nothing
+            // we can do against that, except education ...
+            if ( storedPassword == null )
+            {
+                storedPassword = ArrayUtils.EMPTY_BYTE_ARRAY;
+            }
+
+            // Create the new principal before storing it in the cache
+            principal = new LdapPrincipal( getDirectoryService().getSchemaManager(), bindContext.getDn(), AuthenticationLevel.SIMPLE, storedPassword );
+
+            // Now, update the local cache ONLY if pwdpolicy is not enabled.
+            if( !getDirectoryService().isPwdPolicyEnabled() )
+            {
+                synchronized ( credentialCache )
+                {
+                    credentialCache.put( bindContext.getDn().getNormName(), principal );
+                }
+            }
+        }
+
+        return principal;
+    }
+
+
+    /**
+     * <p>
+     * Looks up <tt>userPassword</tt> attribute of the entry whose name is the
+     * value of {@link Context#SECURITY_PRINCIPAL} environment variable, and
+     * authenticates a user with the plain-text password.
+     * </p>
+     */
+    public LdapPrincipal authenticate( BindOperationContext bindContext ) throws LdapException
+    {
+        if ( IS_DEBUG )
+        {
+            LOG.debug( "Authenticating {}", bindContext.getDn() );
+        }
+
+        // ---- extract password from JNDI environment
+        byte[] credentials = bindContext.getCredentials();
+
+        LdapPrincipal principal = getStoredPassword( bindContext );
+
+        IoSession session = bindContext.getIoSession();
+        
+        if ( session != null )
+        {
+            SocketAddress clientAddress = session.getRemoteAddress();
+            principal.setClientAddress( clientAddress );
+            SocketAddress serverAddress = session.getServiceAddress();
+            principal.setServerAddress( serverAddress );
+        }
+        
+        // Get the stored password, either from cache or from backend
+        byte[] storedPassword = principal.getUserPassword();
+
+        // Now, compare the two passwords.
+        if ( PasswordUtil.compareCredentials( credentials, storedPassword ) )
+        {
+            if ( IS_DEBUG )
+            {
+                LOG.debug( "{} Authenticated", bindContext.getDn() );
+            }
+
+            return principal;
+        }
+        else
+        {
+            // Bad password ...
+            String message = I18n.err( I18n.ERR_230, bindContext.getDn().getName() );
+            LOG.info( message );
+            throw new LdapAuthenticationException( message );
+        }
+    }
+
+
+    /**
+     * Local function which request the password from the backend
+     * @param bindContext the Bind operation context
+     * @return the credentials from the backend
+     * @throws Exception if there are problems accessing backend
+     */
+    private byte[] lookupUserPassword( BindOperationContext bindContext ) throws LdapException
+    {
+        // ---- lookup the principal entry's userPassword attribute
+        Entry userEntry;
+
+        try
+        {
+            /*
+             * NOTE: at this point the BindOperationContext does not has a
+             * null session since the user has not yet authenticated so we
+             * cannot use lookup() yet.  This is a very special
+             * case where we cannot rely on the bindContext to perform a new
+             * sub operation.
+             */
+            LookupOperationContext lookupContext = new LookupOperationContext( getDirectoryService().getAdminSession(),
+                bindContext.getDn() );
+            lookupContext.setByPassed( USERLOOKUP_BYPASS );
+            lookupContext.addAttrsId( SchemaConstants.ALL_USER_ATTRIBUTES );
+            // OP attributes required for ppolicy
+            lookupContext.addAttrsId( SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES );
+            
+            userEntry = getDirectoryService().getOperationManager().lookup( lookupContext );
+
+            if ( userEntry == null )
+            {
+                Dn dn = bindContext.getDn();
+                String upDn = ( dn == null ? "" : dn.getName() );
+
+                throw new LdapAuthenticationException( I18n.err( I18n.ERR_231, upDn ) );
+            }
+        }
+        catch ( Exception cause )
+        {
+            LOG.error( I18n.err( I18n.ERR_6, cause.getLocalizedMessage() ) );
+            LdapAuthenticationException e = new LdapAuthenticationException( cause.getLocalizedMessage() );
+            e.initCause( e );
+            throw e;
+        }
+
+        checkPwdPolicy( userEntry );
+
+        Value<?> userPassword;
+
+        Attribute userPasswordAttr = userEntry.get( SchemaConstants.USER_PASSWORD_AT );
+
+        bindContext.setEntry( new ClonedServerEntry( userEntry ) );
+
+        // ---- assert that credentials match
+        if ( userPasswordAttr == null )
+        {
+            return StringConstants.EMPTY_BYTES;
+        }
+        else
+        {
+            userPassword = userPasswordAttr.get();
+
+            return userPassword.getBytes();
+        }
+    }
+
+
+    /**
+     * Get the algorithm of a password, which is stored in the form "{XYZ}...".
+     * The method returns null, if the argument is not in this form. It returns
+     * XYZ, if XYZ is an algorithm known to the MessageDigest class of
+     * java.security.
+     *
+     * @param password a byte[]
+     * @return included message digest alorithm, if any
+     * @throws IllegalArgumentException if the algorithm cannot be identified
+     */
+    protected String getAlgorithmForHashedPassword( byte[] password ) throws IllegalArgumentException
+    {
+        String result = null;
+
+        // Check if password arg is string or byte[]
+        String sPassword = Strings.utf8ToString(password);
+        int rightParen = sPassword.indexOf( '}' );
+
+        if ( ( sPassword.length() > 2 ) && ( sPassword.charAt( 0 ) == '{' ) && ( rightParen > -1 ) )
+        {
+            String algorithm = sPassword.substring( 1, rightParen );
+
+            if ( LdapSecurityConstants.HASH_METHOD_CRYPT.getName().equalsIgnoreCase( algorithm ) )
+            {
+                return algorithm;
+            }
+
+            try
+            {
+                MessageDigest.getInstance( algorithm );
+                result = algorithm;
+            }
+            catch ( NoSuchAlgorithmException e )
+            {
+                LOG.warn( "Unknown message digest algorithm in password: " + algorithm, e );
+            }
+        }
+
+        return result;
+    }
+
+
+    /**
+     * Creates a digested password. For a given hash algorithm and a password
+     * value, the algorithm is applied to the password, and the result is Base64
+     * encoded. The method returns a String which looks like "{XYZ}bbbbbbb",
+     * whereas XYZ is the name of the algorithm, and bbbbbbb is the Base64
+     * encoded value of XYZ applied to the password.
+     *
+     * @param algorithm
+     *            an algorithm which is supported by
+     *            java.security.MessageDigest, e.g. SHA
+     * @param password
+     *            password value, a byte[]
+     *
+     * @return a digested password, which looks like
+     *         {SHA}LhkDrSoM6qr0fW6hzlfOJQW61tc=
+     *
+     * @throws IllegalArgumentException
+     *             if password is neither a String nor a byte[], or algorithm is
+     *             not known to java.security.MessageDigest class
+     */
+    protected String createDigestedPassword( String algorithm, byte[] password ) throws IllegalArgumentException
+    {
+        // create message digest object
+        try
+        {
+            if ( LdapSecurityConstants.HASH_METHOD_CRYPT.getName().equalsIgnoreCase( algorithm ) )
+            {
+                String saltWithCrypted = UnixCrypt.crypt(Strings.utf8ToString(password), "");
+                String crypted = saltWithCrypted.substring( 2 );
+                return '{' + algorithm + '}' + Arrays.toString( Strings.getBytesUtf8(crypted) );
+            }
+            else
+            {
+                MessageDigest digest = MessageDigest.getInstance( algorithm );
+
+                // calculate hashed value of password
+                byte[] fingerPrint = digest.digest( password );
+                char[] encoded = Base64.encode(fingerPrint);
+
+                // create return result of form "{alg}bbbbbbb"
+                return '{' + algorithm + '}' + new String( encoded );
+            }
+        }
+        catch ( NoSuchAlgorithmException nsae )
+        {
+            LOG.error( I18n.err( I18n.ERR_7, algorithm ) );
+            throw new IllegalArgumentException( nsae.getLocalizedMessage() );
+        }
+    }
+
+
+    /**
+     * Remove the principal form the cache. This is used when the user changes
+     * his password.
+     */
+    public void invalidateCache( Dn bindDn )
+    {
+        synchronized ( credentialCache )
+        {
+            credentialCache.remove( bindDn.getNormName() );
+        }
+    }
+}

Added: directory/apacheds/branches/apacheds-txns/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/StrongAuthenticator.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/StrongAuthenticator.java?rev=1187013&view=auto
==============================================================================
--- directory/apacheds/branches/apacheds-txns/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/StrongAuthenticator.java (added)
+++ directory/apacheds/branches/apacheds-txns/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/StrongAuthenticator.java Thu Oct 20 19:41:49 2011
@@ -0,0 +1,72 @@
+/*
+ *  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.directory.server.core.authn;
+
+
+import java.net.SocketAddress;
+
+import org.apache.directory.server.core.api.LdapPrincipal;
+import org.apache.directory.server.core.api.interceptor.context.BindOperationContext;
+import org.apache.directory.shared.ldap.model.constants.AuthenticationLevel;
+import org.apache.directory.shared.ldap.model.exception.LdapAuthenticationException;
+import org.apache.mina.core.session.IoSession;
+
+
+/**
+ * An {@link Authenticator} that handles SASL connections (X.501 authentication
+ * level <tt>'strong'</tt>).  The principal has been authenticated during SASL
+ * negotiation; therefore, no additional authentication is necessary in this
+ * {@link Authenticator}.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class StrongAuthenticator extends AbstractAuthenticator
+{
+    /**
+     * Creates a new instance of SaslAuthenticator.
+     */
+    public StrongAuthenticator()
+    {
+        super( AuthenticationLevel.STRONG );
+    }
+
+
+    /**
+     * User has already been authenticated during SASL negotiation. Set the authentication level
+     * to strong and return an {@link LdapPrincipal}.
+     */
+    public LdapPrincipal authenticate( BindOperationContext bindContext ) throws LdapAuthenticationException
+    {
+        // Possibly check if user account is disabled, other account checks.
+        LdapPrincipal principal = new LdapPrincipal( getDirectoryService().getSchemaManager(), bindContext.getDn(), AuthenticationLevel.STRONG );
+        
+        IoSession session = bindContext.getIoSession();
+        
+        if ( session != null )
+        {
+            SocketAddress clientAddress = session.getRemoteAddress();
+            principal.setClientAddress( clientAddress );
+            SocketAddress serverAddress = session.getServiceAddress();
+            principal.setServerAddress( serverAddress );
+        }
+        
+        return principal;
+    }
+}

Added: directory/apacheds/branches/apacheds-txns/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/ppolicy/PpolicyConfigContainer.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/ppolicy/PpolicyConfigContainer.java?rev=1187013&view=auto
==============================================================================
--- directory/apacheds/branches/apacheds-txns/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/ppolicy/PpolicyConfigContainer.java (added)
+++ directory/apacheds/branches/apacheds-txns/interceptors/authn/src/main/java/org/apache/directory/server/core/authn/ppolicy/PpolicyConfigContainer.java Thu Oct 20 19:41:49 2011
@@ -0,0 +1,114 @@
+/*
+ *   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.directory.server.core.authn.ppolicy;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.directory.server.core.api.authn.ppolicy.PasswordPolicyConfiguration;
+import org.apache.directory.shared.ldap.model.name.Dn;
+
+
+/**
+ * A container to hold all the password policies defined in the server
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PpolicyConfigContainer
+{
+
+    /** a map holding the entry specific password policies */
+    private Map<Dn, PasswordPolicyConfiguration> ppolicyConfigMap = new HashMap<Dn, PasswordPolicyConfiguration>();
+
+    /** the default password policy */
+    private PasswordPolicyConfiguration defaultPolicy;
+
+
+    /**
+     * add a entry specific policy
+     *
+     * @param configDn the Dn where this entry's password policy is defined
+     * @param policyConfig the password policy configuration
+     */
+    public void addPolicy( Dn configDn, PasswordPolicyConfiguration policyConfig )
+    {
+        if ( configDn == null )
+        {
+            throw new IllegalArgumentException( "password policy config's Dn cannot be null" );
+        }
+
+        ppolicyConfigMap.put( configDn, policyConfig );
+    }
+
+
+    /**
+     * @return true if atleast one entry specific password policy exists, false otherwise
+     */
+    public boolean hasCustomConfigs()
+    {
+        return ( !ppolicyConfigMap.isEmpty() );
+    }
+    
+    
+    /**
+     * Get the password policy configuration defined at a given Dn
+     *  
+     * @param configDn the Dn where password policy was configured
+     * @return
+     */
+    public PasswordPolicyConfiguration getPolicyConfig( Dn configDn )
+    {
+        return ppolicyConfigMap.get( configDn );
+    }
+
+
+    /**
+     * @return the default password policy, null if not configured
+     */
+    public PasswordPolicyConfiguration getDefaultPolicy()
+    {
+        return defaultPolicy;
+    }
+
+
+    /**
+     * Set the default password policy configuration
+     * 
+     * @param defaultPolicy the password policy configuration instance
+     */
+    public void setDefaultPolicy( PasswordPolicyConfiguration defaultPolicy )
+    {
+        this.defaultPolicy = defaultPolicy;
+    }
+
+    
+    /**
+     * deactivate an existing password policy.
+     *  
+     * @param ppolicyConfigDn the Dn of the password policy configuration
+     * @return the deactivated password policy config object of the given reference Dn, null otherwise
+     */
+    public PasswordPolicyConfiguration removePolicyConfig( Dn ppolicyConfigDn )
+    {
+        return ppolicyConfigMap.remove( ppolicyConfigDn );
+    }
+}

Added: directory/apacheds/branches/apacheds-txns/interceptors/authn/src/test/java/org/apache/directory/server/core/authn/LdapPrincipalTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/interceptors/authn/src/test/java/org/apache/directory/server/core/authn/LdapPrincipalTest.java?rev=1187013&view=auto
==============================================================================
--- directory/apacheds/branches/apacheds-txns/interceptors/authn/src/test/java/org/apache/directory/server/core/authn/LdapPrincipalTest.java (added)
+++ directory/apacheds/branches/apacheds-txns/interceptors/authn/src/test/java/org/apache/directory/server/core/authn/LdapPrincipalTest.java Thu Oct 20 19:41:49 2011
@@ -0,0 +1,107 @@
+/*
+ *  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.directory.server.core.authn;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.apache.directory.server.core.api.LdapPrincipal;
+import org.apache.directory.server.core.api.LdapPrincipalSerializer;
+import org.apache.directory.shared.ldap.model.constants.AuthenticationLevel;
+import org.apache.directory.shared.ldap.model.name.Dn;
+import org.apache.directory.shared.ldap.model.schema.SchemaManager;
+import org.apache.directory.shared.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/**
+ * 
+ * Test the LdapPrincipal class
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class LdapPrincipalTest
+{
+    /** The schema manager instance */
+    private static SchemaManager schemaManager;
+
+    @BeforeClass
+    public static void setUp() throws Exception
+    {
+        schemaManager = new DefaultSchemaManager();
+    }
+
+
+    /**
+     * Test the serialization of an empty LdapPrincipal
+     */
+    @Test
+    public void testStaticSerializeEmptyLdapPrincipal() throws Exception
+    {
+        LdapPrincipal principal = new LdapPrincipal( schemaManager );
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        LdapPrincipalSerializer.serialize( principal, out );
+        out.flush();
+
+        byte[] data = baos.toByteArray();
+        ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        LdapPrincipal readPrincipal = LdapPrincipalSerializer.deserialize( schemaManager, in );
+        assertEquals( principal.getAuthenticationLevel(), readPrincipal.getAuthenticationLevel() );
+        assertEquals( principal.getName(), readPrincipal.getName() );
+    }
+    
+    
+    /**
+     * Test the serialization of an empty LdapPrincipal
+     */
+    @Test
+    public void testStaticSerializeLdapPrincipalWithSchemaManager() throws Exception
+    {
+        LdapPrincipal principal = new LdapPrincipal( schemaManager, new Dn( schemaManager, "uid=admin,ou=system" ), AuthenticationLevel.STRONG );
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        LdapPrincipalSerializer.serialize( principal, out );
+        out.flush();
+
+        byte[] data = baos.toByteArray();
+        ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        LdapPrincipal readPrincipal = LdapPrincipalSerializer.deserialize( schemaManager, in );
+        assertEquals( principal.getAuthenticationLevel(), readPrincipal.getAuthenticationLevel() );
+        assertEquals( principal.getName(), readPrincipal.getName() );
+    }
+}

Added: directory/apacheds/branches/apacheds-txns/interceptors/authn/src/test/java/org/apache/directory/server/core/authn/SimpleAuthenticatorOneWayEncryptedTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/interceptors/authn/src/test/java/org/apache/directory/server/core/authn/SimpleAuthenticatorOneWayEncryptedTest.java?rev=1187013&view=auto
==============================================================================
--- directory/apacheds/branches/apacheds-txns/interceptors/authn/src/test/java/org/apache/directory/server/core/authn/SimpleAuthenticatorOneWayEncryptedTest.java (added)
+++ directory/apacheds/branches/apacheds-txns/interceptors/authn/src/test/java/org/apache/directory/server/core/authn/SimpleAuthenticatorOneWayEncryptedTest.java Thu Oct 20 19:41:49 2011
@@ -0,0 +1,80 @@
+/*
+ *  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.directory.server.core.authn;
+
+
+import static org.junit.Assert.assertEquals;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+import org.apache.directory.shared.util.Strings;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Test case for helper methods within SimpleAuthenticator.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class SimpleAuthenticatorOneWayEncryptedTest
+{
+    private static SimpleAuthenticator auth = null;
+
+
+    @BeforeClass
+    public static void setUp() throws Exception
+    {
+
+        auth = new SimpleAuthenticator();
+    }
+
+
+    @Test
+    public void testGetAlgorithmForHashedPassword()
+    {
+        String digestetValue = "{SHA}LhkDrSoM6qr0fW6hzlfOJQW61tc=";
+        assertEquals( "SHA", auth.getAlgorithmForHashedPassword( Strings.getBytesUtf8(digestetValue) ) );
+        assertEquals( "SHA", auth.getAlgorithmForHashedPassword( digestetValue.getBytes() ) );
+
+        String noAlgorithm = "Secret1!";
+        assertEquals( null, auth.getAlgorithmForHashedPassword( Strings.getBytesUtf8(noAlgorithm) ) );
+        assertEquals( null, auth.getAlgorithmForHashedPassword( noAlgorithm.getBytes() ) );
+
+        String unknownAlgorithm = "{XYZ}LhkDrSoM6qr0fW6hzlfOJQW61tc=";
+        assertEquals( null, auth.getAlgorithmForHashedPassword( Strings.getBytesUtf8(unknownAlgorithm) ) );
+        assertEquals( null, auth.getAlgorithmForHashedPassword( unknownAlgorithm.getBytes() ) );
+    }
+
+
+    @Test
+    public void testCreateDigestedPassword() throws IllegalArgumentException
+    {
+        String pwd = "Secret1!";
+        String expected = "{SHA}znbJr3+tymFoQD4+Njh4ITtI7Cc=";
+        String digested = auth.createDigestedPassword( "SHA", Strings.getBytesUtf8(pwd) );
+
+        assertEquals( expected, digested );
+    }
+}
\ No newline at end of file

Propchange: directory/apacheds/branches/apacheds-txns/interceptors/authz/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Oct 20 19:41:49 2011
@@ -0,0 +1,11 @@
+target
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+bin

Propchange: directory/apacheds/branches/apacheds-txns/interceptors/changelog/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Oct 20 19:41:49 2011
@@ -0,0 +1,11 @@
+target
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+bin

Propchange: directory/apacheds/branches/apacheds-txns/interceptors/collective/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Oct 20 19:41:49 2011
@@ -0,0 +1,11 @@
+target
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+bin

Propchange: directory/apacheds/branches/apacheds-txns/interceptors/event/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Oct 20 19:41:49 2011
@@ -0,0 +1,12 @@
+target
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+bin
+

Propchange: directory/apacheds/branches/apacheds-txns/interceptors/exception/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Oct 20 19:41:49 2011
@@ -0,0 +1,11 @@
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+bin
+target

Propchange: directory/apacheds/branches/apacheds-txns/interceptors/hash/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Oct 20 19:41:49 2011
@@ -0,0 +1,11 @@
+target
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+bin

Propchange: directory/apacheds/branches/apacheds-txns/interceptors/journal/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Oct 20 19:41:49 2011
@@ -0,0 +1,11 @@
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+target
+bin

Propchange: directory/apacheds/branches/apacheds-txns/interceptors/logger/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Oct 20 19:41:49 2011
@@ -0,0 +1,11 @@
+target
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+bin

Propchange: directory/apacheds/branches/apacheds-txns/interceptors/normalization/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Oct 20 19:41:49 2011
@@ -0,0 +1,11 @@
+target
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+bin

Propchange: directory/apacheds/branches/apacheds-txns/interceptors/operational/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Oct 20 19:41:49 2011
@@ -0,0 +1,11 @@
+target
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+bin

Propchange: directory/apacheds/branches/apacheds-txns/interceptors/referral/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Oct 20 19:41:49 2011
@@ -0,0 +1,11 @@
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+target
+bin

Propchange: directory/apacheds/branches/apacheds-txns/interceptors/schema/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Oct 20 19:41:49 2011
@@ -0,0 +1,11 @@
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+bin
+target

Propchange: directory/apacheds/branches/apacheds-txns/interceptors/subtree/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Oct 20 19:41:49 2011
@@ -0,0 +1,11 @@
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+bin
+target

Propchange: directory/apacheds/branches/apacheds-txns/interceptors/trigger/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Oct 20 19:41:49 2011
@@ -0,0 +1,12 @@
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+target
+bin
+

Propchange: directory/apacheds/branches/apacheds-txns/jdbm/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Oct 20 19:41:49 2011
@@ -4,5 +4,6 @@
 /directory/apacheds/branches/apacheds-jdbm/jdbm:1160768-1164076
 /directory/apacheds/branches/apacheds-kerberos-codec-2.0/jdbm:1040956-1043765
 /directory/apacheds/branches/milestones/jdbm:1072812-1075328
-/directory/apacheds/trunk/jdbm:1066126-1067785,1068026-1072718,1072800-1075329
+/directory/apacheds/trunk/interceptors/jdbm:1183435-1186974
+/directory/apacheds/trunk/jdbm:1066126-1067785,1068026-1072718,1072800-1075329,1177661-1186962
 /directory/studio/trunk/jdbm:1067786-1067997

Propchange: directory/apacheds/branches/apacheds-txns/jdbm-partition/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Oct 20 19:41:49 2011
@@ -4,5 +4,6 @@
 /directory/apacheds/branches/apacheds-jdbm/jdbm-partition:1160768-1164080
 /directory/apacheds/branches/apacheds-kerberos-codec-2.0/jdbm-partition:1040956-1043765
 /directory/apacheds/branches/milestones/jdbm-partition:1072812-1075328
-/directory/apacheds/trunk/jdbm-partition:1066126-1067785,1068026-1072718,1072800-1075329
+/directory/apacheds/trunk/interceptors/jdbm-partition:1183435-1186974
+/directory/apacheds/trunk/jdbm-partition:1066126-1067785,1068026-1072718,1072800-1075329,1177661-1186962
 /directory/studio/trunk/jdbm-partition:1067786-1067997

Modified: directory/apacheds/branches/apacheds-txns/jdbm-partition/pom.xml
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/jdbm-partition/pom.xml?rev=1187013&r1=1187012&r2=1187013&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/jdbm-partition/pom.xml (original)
+++ directory/apacheds/branches/apacheds-txns/jdbm-partition/pom.xml Thu Oct 20 19:41:49 2011
@@ -27,6 +27,7 @@
   
   <artifactId>apacheds-jdbm-partition</artifactId>
   <name>ApacheDS JDBM Partition</name>
+  <packaging>bundle</packaging>
 
   <description>
     JDBM BTree backed partition implementation.
@@ -122,6 +123,33 @@
           </execution>
         </executions>
       </plugin>
+      
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <manifestFile>META-INF/MANIFEST.MF</manifestFile>
+            <addMavenDescriptor>false</addMavenDescriptor>
+          </archive>
+        </configuration>
+      </plugin>
+      
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <inherited>true</inherited>
+        <extensions>true</extensions>
+        <configuration>
+          <manifestLocation>META-INF</manifestLocation>
+          <instructions>
+            <Bundle-SymbolicName>${project.groupId}.jdbm.partition</Bundle-SymbolicName>
+            <Export-Package>
+                org.apache.directory.server.core.partition.impl.btree.jdbm;version=${project.version};-noimport:=true
+            </Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
     </plugins>
   </build>
 </project>

Modified: directory/apacheds/branches/apacheds-txns/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java?rev=1187013&r1=1187012&r2=1187013&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java (original)
+++ directory/apacheds/branches/apacheds-txns/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java Thu Oct 20 19:41:49 2011
@@ -22,6 +22,7 @@ package org.apache.directory.server.core
 
 import java.io.File;
 import java.io.FilenameFilter;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -31,7 +32,7 @@ import jdbm.recman.BaseRecordManager;
 import jdbm.recman.SnapshotRecordManager;
 
 import org.apache.directory.server.constants.ApacheSchemaConstants;
-import org.apache.directory.server.core.partition.Partition;
+import org.apache.directory.server.core.api.partition.Partition;
 import org.apache.directory.server.core.partition.impl.btree.AbstractBTreePartition;
 import org.apache.directory.server.i18n.I18n;
 import org.apache.directory.server.core.partition.index.Index;
@@ -119,7 +120,10 @@ public class JdbmPartition extends Abstr
 
             // Create the underlying directories (only if needed)
             File partitionDir = new File( getPartitionPath() );
-            partitionDir.mkdirs();
+            if ( !partitionDir.exists() && !partitionDir.mkdirs() )
+            {
+                throw new IOException(I18n.err( I18n.ERR_112_COULD_NOT_CREATE_DIRECORY, partitionDir ));
+            }
     
             // Initialize the indexes
             super.doInit();

Modified: directory/apacheds/branches/apacheds-txns/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java?rev=1187013&r1=1187012&r2=1187013&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java (original)
+++ directory/apacheds/branches/apacheds-txns/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java Thu Oct 20 19:41:49 2011
@@ -34,8 +34,8 @@ import java.util.UUID;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.directory.server.constants.ApacheSchemaConstants;
-import org.apache.directory.server.core.interceptor.context.AddOperationContext;
-import org.apache.directory.server.core.interceptor.context.LookupOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
 import org.apache.directory.server.core.partition.index.GenericIndex;
 import org.apache.directory.server.core.partition.index.Index;
 import org.apache.directory.server.core.partition.index.IndexEntry;
@@ -140,7 +140,6 @@ public class JdbmStoreTest
         wkdir = File.createTempFile( getClass().getSimpleName(), "db" );
         wkdir.delete();
         wkdir = new File( wkdir.getParentFile(), getClass().getSimpleName() );
-        wkdir.mkdirs();
 
         // initialize the store
         store = new JdbmPartition( schemaManager );
@@ -199,7 +198,6 @@ public class JdbmStoreTest
         File wkdir2 = File.createTempFile( getClass().getSimpleName(), "db2" );
         wkdir2.delete();
         wkdir2 = new File( wkdir2.getParentFile(), getClass().getSimpleName() );
-        wkdir2.mkdirs();
 
         // initialize the 2nd store
         JdbmPartition store2 = new JdbmPartition( schemaManager );

Propchange: directory/apacheds/branches/apacheds-txns/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Oct 20 19:41:49 2011
@@ -8,5 +8,6 @@
 /directory/apacheds/branches/apacheds-subtree/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree:965203-965686
 /directory/apacheds/branches/milestones/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree:1072812-1075328
 /directory/apacheds/branches/xdbm-refactoring/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree:945827-946347
-/directory/apacheds/trunk/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree:498338-580500,806623-894866*,1066126-1067785,1068026-1072718,1072800-1075329
+/directory/apacheds/trunk/interceptors/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree:1183435-1186974
+/directory/apacheds/trunk/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree:498338-580500,806623-894866*,1066126-1067785,1068026-1072718,1072800-1075329,1177661-1186962
 /directory/studio/trunk/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree:1067786-1067997

Modified: directory/apacheds/branches/apacheds-txns/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree/PartitionTreeTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree/PartitionTreeTest.java?rev=1187013&r1=1187012&r2=1187013&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree/PartitionTreeTest.java (original)
+++ directory/apacheds/branches/apacheds-txns/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree/PartitionTreeTest.java Thu Oct 20 19:41:49 2011
@@ -27,7 +27,7 @@ import static org.junit.Assert.fail;
 
 import java.io.File;
 
-import org.apache.directory.server.core.partition.Partition;
+import org.apache.directory.server.core.api.partition.Partition;
 import org.apache.directory.server.core.partition.impl.btree.jdbm.DupsContainerCursorTest;
 import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition;
 import org.apache.directory.shared.ldap.model.exception.LdapException;

Propchange: directory/apacheds/branches/apacheds-txns/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree/PartitionTreeTest.java
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Oct 20 19:41:49 2011
@@ -8,5 +8,6 @@
 /directory/apacheds/branches/apacheds-subtree/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree/PartitionTreeTest.java:965203-965686
 /directory/apacheds/branches/milestones/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree/PartitionTreeTest.java:1072812-1075328
 /directory/apacheds/branches/xdbm-refactoring/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree/PartitionTreeTest.java:945827-946347
-/directory/apacheds/trunk/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree/PartitionTreeTest.java:498338-580500,806623-894866,1066126-1067785,1068026-1072718,1072800-1075329
+/directory/apacheds/trunk/interceptors/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree/PartitionTreeTest.java:1183435-1186974
+/directory/apacheds/trunk/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree/PartitionTreeTest.java:498338-580500,806623-894866,1066126-1067785,1068026-1072718,1072800-1075329,1177661-1186962
 /directory/studio/trunk/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/tree/PartitionTreeTest.java:1067786-1067997

Modified: directory/apacheds/branches/apacheds-txns/jdbm/pom.xml
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/jdbm/pom.xml?rev=1187013&r1=1187012&r2=1187013&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/jdbm/pom.xml (original)
+++ directory/apacheds/branches/apacheds-txns/jdbm/pom.xml Thu Oct 20 19:41:49 2011
@@ -27,6 +27,7 @@
   
   <artifactId>apacheds-jdbm</artifactId>
   <name>ApacheDS JDBM implementation</name>
+  <packaging>bundle</packaging>
 
   <description>Specific JDBM Implementation</description>
 
@@ -58,5 +59,33 @@
          </plugin>
       </plugins>
     </pluginManagement>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <manifestFile>META-INF/MANIFEST.MF</manifestFile>
+            <addMavenDescriptor>false</addMavenDescriptor>
+          </archive>
+        </configuration>
+      </plugin>
+    
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <inherited>true</inherited>
+        <extensions>true</extensions>
+        <configuration>
+          <manifestLocation>META-INF</manifestLocation>
+          <instructions>
+            <Bundle-SymbolicName>${project.groupId}.jdbm</Bundle-SymbolicName>
+            <Export-Package>
+                {local-packages};version=${project.version};-noimport:=true
+            </Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
   </build>
 </project>

Modified: directory/apacheds/branches/apacheds-txns/jdbm/src/examples/FamousPeople.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/jdbm/src/examples/FamousPeople.java?rev=1187013&r1=1187012&r2=1187013&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/jdbm/src/examples/FamousPeople.java (original)
+++ directory/apacheds/branches/apacheds-txns/jdbm/src/examples/FamousPeople.java Thu Oct 20 19:41:49 2011
@@ -1,4 +1,3 @@
-
 import java.util.Properties;
 import jdbm.RecordManager;
 import jdbm.RecordManagerFactory;

Modified: directory/apacheds/branches/apacheds-txns/jdbm/src/examples/FruitBasket.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/jdbm/src/examples/FruitBasket.java?rev=1187013&r1=1187012&r2=1187013&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/jdbm/src/examples/FruitBasket.java (original)
+++ directory/apacheds/branches/apacheds-txns/jdbm/src/examples/FruitBasket.java Thu Oct 20 19:41:49 2011
@@ -1,4 +1,3 @@
-
 import jdbm.RecordManager;
 import jdbm.RecordManagerFactory;
 import jdbm.helper.FastIterator;

Modified: directory/apacheds/branches/apacheds-txns/jdbm/src/examples/Primes.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/jdbm/src/examples/Primes.java?rev=1187013&r1=1187012&r2=1187013&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/jdbm/src/examples/Primes.java (original)
+++ directory/apacheds/branches/apacheds-txns/jdbm/src/examples/Primes.java Thu Oct 20 19:41:49 2011
@@ -1,4 +1,3 @@
-
 import jdbm.RecordManager;
 import jdbm.RecordManagerFactory;
 import jdbm.RecordManagerOptions;

Modified: directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/btree/BTree.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/btree/BTree.java?rev=1187013&r1=1187012&r2=1187013&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/btree/BTree.java (original)
+++ directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/btree/BTree.java Thu Oct 20 19:41:49 2011
@@ -743,7 +743,10 @@ public class BTree<K, V> implements Exte
      */
     BPage<K, V> getRoot( ) throws IOException
     {        
-        assert( this.rootId == metaRoot.rootID) : "Stale root id " + this.rootId + " "+ metaRoot.rootID;
+        if ( rootId != metaRoot.rootID )
+        {
+            throw new IllegalStateException( "Stale root id " + this.rootId + " "+ metaRoot.rootID );
+        }
         
         if ( this.rootId == 0 )
         {
@@ -864,7 +867,6 @@ public class BTree<K, V> implements Exte
     {
         if ( context != null )
         {
-            assert( isActionCapable == true );
             ( ( ActionRecordManager )recordManager ).setCurrentActionContext( context );
         }
     }
@@ -874,7 +876,6 @@ public class BTree<K, V> implements Exte
     {
         if ( context != null )
         {
-            assert( isActionCapable == true );
             ( ( ActionRecordManager )recordManager ).unsetCurrentActionContext( context );
         }
     }
@@ -897,7 +898,6 @@ public class BTree<K, V> implements Exte
     {
         if ( context != null )
         {
-            assert( isActionCapable );
             ( ( ActionRecordManager )recordManager ).endAction( context );
         }
     }
@@ -907,7 +907,6 @@ public class BTree<K, V> implements Exte
     {
         if ( context != null )
         {
-            assert( isActionCapable );
             ( ( ActionRecordManager )recordManager ).abortAction( context );
         }
 

Modified: directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/helper/ActionContext.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/helper/ActionContext.java?rev=1187013&r1=1187012&r2=1187013&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/helper/ActionContext.java (original)
+++ directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/helper/ActionContext.java Thu Oct 20 19:41:49 2011
@@ -45,7 +45,11 @@ public class ActionContext
     
     public void endAction()
     {
-        assert( version != null ) : "Unexpected action state during endAction: " + this;
+        if ( version == null )
+        {
+            throw new IllegalStateException( "Unexpected action state during endAction: " + this );
+        }
+        
         version = null;
     }
     

Modified: directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/helper/ActionVersioning.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/helper/ActionVersioning.java?rev=1187013&r1=1187012&r2=1187013&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/helper/ActionVersioning.java (original)
+++ directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/helper/ActionVersioning.java Thu Oct 20 19:41:49 2011
@@ -153,7 +153,11 @@ public class ActionVersioning
     {
         long numActions = version.getNumActions().decrementAndGet();
         
-        assert( numActions >= 0 ) : "NumActions zero when read action is ended : " + version;
+        if ( numActions < 0 )
+        {
+            throw new IllegalStateException( "NumActions zero when read action is ended : " + version );
+        }
+
         
         if ( ( numActions > 0 ) || ( version == readReference.get() ) )
         {

Modified: directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/helper/ExplicitList.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/helper/ExplicitList.java?rev=1187013&r1=1187012&r2=1187013&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/helper/ExplicitList.java (original)
+++ directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/helper/ExplicitList.java Thu Oct 20 19:41:49 2011
@@ -75,7 +75,11 @@ public class ExplicitList<T>
 
         public void remove()
         {
-            assert( isLinked() ) : "Trying to remove from list an unlinked link";
+            if ( isLinked() == false )
+            {
+                throw new IllegalStateException( "Trying to remove from list an unlinked link" );
+            }
+ 
             this.getPrev().setNext( this.getNext() );
             this.getNext().setPrev( this.getPrev() );
             this.reset();
@@ -84,7 +88,11 @@ public class ExplicitList<T>
 
         public void addAfter( Link<V> after )
         {
-            assert( this.isUnLinked() ) : "Trying to add to list already linked link: " + this;
+            if ( this.isUnLinked() == false )
+            {
+                throw new IllegalStateException( "Trying to add to list already linked link: " + this );
+            }
+            
             after.getNext().setPrev( this );
             this.setNext( after.getNext() );
             after.setNext( this );
@@ -94,7 +102,11 @@ public class ExplicitList<T>
 
         public void addBefore( Link<V> before )
         {
-            assert( this.isUnLinked() ) : "Trying to add to list already linked link: " + this;
+            if ( this.isUnLinked() == false )
+            {
+                throw new IllegalStateException( "Trying to add to list already linked link: " + this );
+            }
+  
             before.getPrev().setNext( this );
             this.setPrev( before.getPrev() );
             before.setPrev( this );
@@ -138,7 +150,11 @@ public class ExplicitList<T>
 
         public void uninit()
         {
-            assert ( this.isUnLinked() ) :  " Unitializing a still linked entry" + this;
+            if ( this.isUnLinked() == false )
+            {
+                throw new IllegalStateException( " Unitializing a still linked entry" + this );
+            }
+   
             element = null;
         }
 
@@ -164,7 +180,11 @@ public class ExplicitList<T>
 
     public void remove( Link<T> link )
     {
-        assert( listSize > 0 ) : "Trying to remove link " + link + " from a list with no elements";
+        if ( listSize <= 0 )
+        {
+            throw new IllegalStateException( "Trying to remove link " + link + " from a list with no elements" );
+        }
+
         listSize--;
         link.remove();
     }

Modified: directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/helper/LRUCache.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/helper/LRUCache.java?rev=1187013&r1=1187012&r2=1187013&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/helper/LRUCache.java (original)
+++ directory/apacheds/branches/apacheds-txns/jdbm/src/main/java/jdbm/helper/LRUCache.java Thu Oct 20 19:41:49 2011
@@ -238,8 +238,11 @@ public class LRUCache<K, V>
                             
                             if ( !entry.isCurrentVersion() )
                             {
-                                assert( entry.isNeverReplace() == false ) : " Non current entry should not have neverReplace set " + entry; 
-                                
+                                if ( entry.isNeverReplace() == true )
+                                {
+                                    throw new IllegalStateException( " Non current entry should not have neverReplace set " + entry );
+                                }
+                                                            
                                 entry.setNeverReplace();
                                 CacheEntry newEntry = null;
                                 
@@ -293,7 +296,7 @@ public class LRUCache<K, V>
                             // FALLTHROUGH
                             
                         default:
-                            assert ( false ): "Unknown cache entry state: " + entry ;
+                            throw new IllegalStateException( "Unknown cache entry state: " + entry ) ;
                     }
                 }
                 else
@@ -414,7 +417,10 @@ public class LRUCache<K, V>
                             
                             this.cacheMisses++;
                             
-                            assert( entry.isNeverReplace() == false ) : "Non Current Entry has neverReplace set to true:" + entry;
+                            if ( entry.isNeverReplace() == true )
+                            {
+                                throw new IllegalStateException( "Non Current Entry has neverReplace set to true:" + entry );
+                            }
                             
                             entry.setNeverReplace();
                             CacheEntry newEntry = null;
@@ -466,7 +472,7 @@ public class LRUCache<K, V>
                         break;
 
                     default:
-                        assert ( false ) : "Unknown cache entry state: " + entry;
+                        throw new IllegalStateException( "Unknown cache entry state: " + entry );
                 }
             }
             else
@@ -569,7 +575,10 @@ public class LRUCache<K, V>
         }
         else
         {
-            assert( entry.isCurrentVersion() ) : "Entry not at expected version: " + entry ;
+            if  ( entry.isCurrentVersion() == false )
+            {
+                throw new IllegalStateException( "Entry not at expected version: " + entry );
+            }
             
             // Entry already at current version. Just update the value
             entry.setAsCurrentVersion( value, newVersion );
@@ -650,15 +659,19 @@ public class LRUCache<K, V>
             
             if ( curEntry.getState() != EntryState.ENTRY_READY )
             {
-                assert( curEntry == head ) : "Unexpected state for entry: " + curEntry;
+                if ( curEntry != head )
+                {
+                    throw new IllegalStateException( "Unexpected state for entry: " + curEntry );
+                }
+    
                 curLink = curLink.getNext();
                 continue;
             }
         
             if ( curStartVersion != 0 && ( curEntry.getEndVersion() > curStartVersion ) )
             {
-                assert( false ) : "Unexpected version number for entry. curStartVersion: " 
-                        + curStartVersion + " entry: " + curEntry;
+                throw new IllegalStateException( "Unexpected version number for entry. curStartVersion: " 
+                        + curStartVersion + " entry: " + curEntry );
             }
             
             curStartVersion = curEntry.getStartVersion();
@@ -686,7 +699,7 @@ public class LRUCache<K, V>
         
         if ( value == null && mustFind == true )
         {
-            assert( false ) : "Traversed all versions and could not find cache entry";
+            throw new IllegalStateException( "Traversed all versions and could not find cache entry" );
         }
         
         return value;
@@ -937,14 +950,26 @@ public class LRUCache<K, V>
             endVersion = Long.MAX_VALUE;
 
             stateCondition = null;
-            assert ( numWaiters == 0 ) : "Numwaiters is not zero when entry is newly initialized: " + this;
+            
+            if ( numWaiters != 0 )
+            {
+                throw new IllegalStateException( "Numwaiters is not zero when entry is newly initialized: " + this );
+            }
+   
             state = EntryState.ENTRY_INITIAL;
 
-            assert ( versionsLink.isUnLinked() == true );
+            if ( versionsLink.isUnLinked() == false )
+            {
+                throw new IllegalStateException( "Versions link is still linked when entry is initialized" );
+            }
+           
             
             hashIndex = hash( key ) & ( numBuckets - 1 );
             
-            assert( neverReplace == false ) : "Neverreplace is true when entry is newly intialized:" + this;
+            if ( neverReplace == true )
+            {
+                throw new IllegalStateException( "Neverreplace is true when entry is newly intialized:" + this );
+            }
         }
 
         public void setNeverReplace()
@@ -1006,7 +1031,11 @@ public class LRUCache<K, V>
 
         public void decrementWaiters()
         {
-            assert ( numWaiters > 0 ) : "Unexpected num waiters for entry:" + this;
+            if ( numWaiters <= 0 )
+            {
+                throw new IllegalStateException( "Unexpected num waiters for entry:" + this );
+            }
+            
             numWaiters--;
         }
 
@@ -1223,9 +1252,11 @@ public class LRUCache<K, V>
                 {
                     break;
                 }
-                               
-                assert( victimEntry.getKey() != null ) : 
-                    "Snapshot victimEntry doesnt have key set:" + victimEntry ;
+                      
+                if ( victimEntry.getKey() == null )
+                {
+                    throw new IllegalStateException( "Snapshot victimEntry doesnt have key set:" + victimEntry );
+                }
                 
                 if ( victimEntry.isNeverReplace() )
                 {
@@ -1242,8 +1273,10 @@ public class LRUCache<K, V>
                     continue;
                 }
                 
-                assert( victimEntry.isEntryFreeable() == true ) : 
-                    "Snapshot victimEntry is not freeable:" + victimEntry ;
+                if ( victimEntry.isEntryFreeable() == false )
+                {
+                    throw new IllegalStateException( "Snapshot victimEntry is not freeable:" + victimEntry );
+                }
                 
                 int hashChainIndex = buckets[victimEntry.getHashIndex()].indexOf( victimEntry );
                 



Mime
View raw message