Return-Path: X-Original-To: apmail-directory-commits-archive@www.apache.org Delivered-To: apmail-directory-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A09B77DC4 for ; Thu, 20 Oct 2011 19:43:18 +0000 (UTC) Received: (qmail 81298 invoked by uid 500); 20 Oct 2011 19:43:18 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 81240 invoked by uid 500); 20 Oct 2011 19:43:18 -0000 Mailing-List: contact commits-help@directory.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@directory.apache.org Delivered-To: mailing list commits@directory.apache.org Received: (qmail 81224 invoked by uid 99); 20 Oct 2011 19:43:18 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 20 Oct 2011 19:43:18 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 20 Oct 2011 19:43:14 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 212AC2388AF0 for ; Thu, 20 Oct 2011 19:42:30 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit 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 -0000 To: commits@directory.apache.org From: elecharny@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20111020194230.212AC2388AF0@eris.apache.org> 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 Apache Directory Project + */ +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 : + *
    + *
  • - SHA
  • + *
  • - SSHA (salted SHA)
  • + *
  • - SHA-2(256, 384 and 512 and their salted versions)
  • + *
  • - MD5
  • + *
  • - SMD5 (slated MD5)
  • + *
  • - crypt (unix crypt)
  • + *
  • - plain text, ie no encryption.
  • + *
+ *

+ * If we get an encrypted password, it is prefixed by the used algorithm, between + * brackets : {SSHA}password ... + *

+ * If the password is using SSHA, SMD5 or crypt, some 'salt' is added to the password : + *
    + *
  • - length(password) - 20, starting at 21th position for SSHA
  • + *
  • - length(password) - 16, starting at 16th position for SMD5
  • + *
  • - length(password) - 2, starting at 3rd position for crypt
  • + *
+ *

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

+ *

+ * For crypt, we only have to remove the salt. + *

+ *

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

+ *

+ * The stored password is always using the unsalted form, and is stored as a bytes array. + *

+ * + * @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> valList = new ArrayList>(); + + 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 userPassword 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 Apache Directory Project + */ +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 USERLOOKUP_BYPASS; + + static + { + Set c = new HashSet(); + 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; + } + + + /** + *

+ * Looks up userPassword 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. + *

+ */ + 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 'strong'). The principal has been authenticated during SASL + * negotiation; therefore, no additional authentication is necessary in this + * {@link Authenticator}. + * + * @author Apache Directory Project + */ +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 Apache Directory Project + */ +public class PpolicyConfigContainer +{ + + /** a map holding the entry specific password policies */ + private Map ppolicyConfigMap = new HashMap(); + + /** 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 Apache Directory Project + */ +@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 Apache Directory Project + */ +@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 @@ apacheds-jdbm-partition ApacheDS JDBM Partition + bundle JDBM BTree backed partition implementation. @@ -122,6 +123,33 @@ + + + org.apache.maven.plugins + maven-jar-plugin + + + META-INF/MANIFEST.MF + false + + + + + + org.apache.felix + maven-bundle-plugin + true + true + + META-INF + + ${project.groupId}.jdbm.partition + + org.apache.directory.server.core.partition.impl.btree.jdbm;version=${project.version};-noimport:=true + + + + 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 @@ apacheds-jdbm ApacheDS JDBM implementation + bundle Specific JDBM Implementation @@ -58,5 +59,33 @@ + + + org.apache.maven.plugins + maven-jar-plugin + + + META-INF/MANIFEST.MF + false + + + + + + org.apache.felix + maven-bundle-plugin + true + true + + META-INF + + ${project.groupId}.jdbm + + {local-packages};version=${project.version};-noimport:=true + + + + + 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 implements Exte */ BPage 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 implements Exte { if ( context != null ) { - assert( isActionCapable == true ); ( ( ActionRecordManager )recordManager ).setCurrentActionContext( context ); } } @@ -874,7 +876,6 @@ public class BTree implements Exte { if ( context != null ) { - assert( isActionCapable == true ); ( ( ActionRecordManager )recordManager ).unsetCurrentActionContext( context ); } } @@ -897,7 +898,6 @@ public class BTree implements Exte { if ( context != null ) { - assert( isActionCapable ); ( ( ActionRecordManager )recordManager ).endAction( context ); } } @@ -907,7 +907,6 @@ public class BTree 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 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 public void addAfter( Link 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 public void addBefore( Link 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 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 public void remove( Link 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 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 // 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 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 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 } 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 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 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 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 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 { 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 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 );