You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by dl...@apache.org on 2005/02/21 22:34:47 UTC

cvs commit: jakarta-jetspeed-2/components/security/src/test/org/apache/jetspeed/security TestAuthenticationProviderProxy.java

dlestrat    2005/02/21 13:34:47

  Modified:    xdocs    navigation.xml
               components/security/src/java/org/apache/jetspeed/security/spi/impl
                        LdapCredentialHandler.java
                        LdapUserSecurityHandler.java
               components/security/src/test/org/apache/jetspeed/security
                        TestAuthenticationProviderProxy.java
  Added:       components/security/src/java/org/apache/jetspeed/security/spi/impl/ldap
                        LdapUserSecurityDao.java
                        LdapUserCredentialDaoImpl.java
                        LdapUserCredentialDao.java
                        LdapUserSecurityDaoImpl.java LdapUserDao.java
                        AbstractLdapDao.java
               components/security/src/test/org/apache/jetspeed/security/spi/ldap
                        AbstractLdapTest.java
                        TestLdapCredentialHandler.java
                        TestLdapUserSecurityHandler.java
                        TestLdapUserCredentialDao.java
                        TestLdapUserSecurityDao.java
               components/security/etc security-spi-ldap.xml
                        ldap.properties security-spi-ldap-atn.xml
  Log:
  http://issues.apache.org/jira/browse/JS2-188#action_59540
  LDAP Security Implementation.  Services Code provided by Mike Long.
  
  Revision  Changes    Path
  1.1                  jakarta-jetspeed-2/components/security/src/java/org/apache/jetspeed/security/spi/impl/ldap/LdapUserSecurityDao.java
  
  Index: LdapUserSecurityDao.java
  ===================================================================
  /*
   * Copyright 2000-2001,2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.jetspeed.security.spi.impl.ldap;
  
  import java.security.Principal;
  
  import org.apache.jetspeed.security.SecurityException;
  
  /**
   * <p>
   * Ldap dao for user security implementation.
   * </p>
   * 
   * @author <a href="mailto:mike.long@dataline.com">Mike Long </a>
   */
  public interface LdapUserSecurityDao extends LdapUserDao
  {
      /**
       * <p>
       * Makes a new ldap entry for the specified user.
       * </p>
       * 
       * @param uid The uid.
       * @throws SecurityException Throws a {@link SecurityException}.
       */
      public abstract void create(final String uid) throws SecurityException;
  
      /**
       * <p>
       * Delete a user by uid.
       * </p>
       * 
       * @param uid The uid.
       * @throws SecurityException Throws a {@link SecurityException}.
       */
      public abstract void delete(final String uid) throws SecurityException;
  
      /**
       * <p>
       * Find the uid principals.
       * </p>
       * 
       * @param uid The uid.
       * @throws SecurityException Throws a {@link SecurityException}.
       */
      public Principal[] find(final String uid) throws SecurityException;
  }
  
  
  1.1                  jakarta-jetspeed-2/components/security/src/java/org/apache/jetspeed/security/spi/impl/ldap/LdapUserCredentialDaoImpl.java
  
  Index: LdapUserCredentialDaoImpl.java
  ===================================================================
  /*
   * Copyright 2000-2001,2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.jetspeed.security.spi.impl.ldap;
  
  import javax.naming.Name;
  import javax.naming.NameParser;
  import javax.naming.NamingEnumeration;
  import javax.naming.NamingException;
  import javax.naming.directory.Attribute;
  import javax.naming.directory.Attributes;
  import javax.naming.directory.BasicAttributes;
  import javax.naming.directory.DirContext;
  import javax.naming.directory.SearchControls;
  import javax.naming.directory.SearchResult;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.jetspeed.security.SecurityException;
  
  /**
   * @see org.apache.jetspeed.security.spi.impl.ldap.LdapUserCredentialDao
   * @author <a href="mailto:mike.long@dataline.com">Mike Long </a>
   */
  public class LdapUserCredentialDaoImpl extends AbstractLdapDao implements LdapUserCredentialDao
  {
      /** The logger. */
      private static final Log LOG = LogFactory.getLog(LdapUserCredentialDaoImpl.class);
  
      /** The password attribute. */ 
      private static final String PASSWORD_ATTR_NAME = "userPassword";
  
      /**
       * <p>
       * Default constructor.
       * </p>
       */
      public LdapUserCredentialDaoImpl()
      {
          super();
      }
      
      /**
       * <p>
       * Initializes the dao.
       * </p>
       * 
       * @param ldapServerName The server name.
       * @param rootDn The root domain.
       * @param rootPassword The root password.
       * @param rootContext The root context.
       * @param defaultDnSuffix The default suffix.
       */
      public LdapUserCredentialDaoImpl(String ldapServerName, String rootDn, String rootPassword, String rootContext,
              String defaultDnSuffix)
      {
          super(ldapServerName, rootDn, rootPassword, rootContext, defaultDnSuffix);
      }
      
      /**
       * <p>
       * Updates the password for the specified user.
       * </p>
       */
      public void changePassword(final String uid, final String password) throws SecurityException
      {
          validateUid(uid);
          validatePassword(password);
          String userDn = lookupByUid(uid);
          try
          {
              setPassword(userDn, password);
          }
          catch (NamingException e)
          {
              throw new SecurityException(e);
          }
      }
  
      /**
       * <p>
       * Looks up the user by the UID attribute. If this lookup succeeds, this
       * method then attempts to authenticate the user using the password,
       * throwing an AuthenticationException if the password is incorrect or an
       * OperationNotSupportedException if the password is empty.
       * </p>
       * 
       * @param uid The uid.
       * @param password The password.
       * @throws SecurityException Throws a {@link SecurityException}.
       */
      public boolean authenticate(final String uid, final String password) throws SecurityException
      {
          try
          {
              validateUid(uid);
              validatePassword(password);
  
              String userDn = lookupByUid(uid);
  
              return isAuthenticatedUser(password, userDn);
          }
          catch (IllegalArgumentException e)
          {
              throw new SecurityException(e);
          }
          catch (NamingException e)
          {
              throw new SecurityException(e);
          }
      }
  
      /**
       * @see org.apache.jetspeed.security.spi.impl.ldap.LdapUserCredentialDao#getPassword(java.lang.String)
       */
      public char[] getPassword(final String uid) throws SecurityException
      {
          try
          {
              bindToServer(this.rootDn, this.rootPassword);
              SearchControls cons = setSearchControls();
              NamingEnumeration results = searchByExplicitUid(uid, cons);
  
              return getPassword(results, uid);
          }
          catch (NamingException e)
          {
              throw new SecurityException(e);
          }
  
      }
  
      /**
       * <p>
       * Set the user's password.
       * </p>
       * 
       * @param userDn The user.
       * @param password The password.
       * @throws NamingException Throws a {@link NamingException}.
       */
      private void setPassword(final String userDn, final String password) throws NamingException
      {
          String rdn = getSubcontextName(userDn);
          Attributes attrs = new BasicAttributes(false);
  
          attrs.put("userPassword", password);
          ctx.modifyAttributes(rdn, DirContext.REPLACE_ATTRIBUTE, attrs);
      }
  
      /**
       * <p>
       * Get the sub context name.
       * </p>
       * 
       * @param dn The domain name.
       * @return The sub context name.
       * @throws NamingException Throws a {@link NamingException}.
       */
      private String getSubcontextName(final String dn) throws NamingException
      {
          NameParser parser = ctx.getNameParser("");
          Name name = parser.parse(dn);
          String rootStr = ctx.getNameInNamespace();
          Name root = parser.parse(rootStr);
  
          if (name.startsWith(root))
          {
              Name rname = name.getSuffix(root.size());
  
              return rname.toString();
          }
  
          return dn;
      }
  
      /**
       * <p>
       * Whether the user is authenticated.
       * </p>
       * 
       * @param password The password.
       * @param userDn The user.
       * @return Whether the user is authenticated.
       * @throws NamingException Throws a {@link NamingException}.
       */
      private boolean isAuthenticatedUser(final String password, String userDn) throws NamingException
      {
          if (userDn == null)
          {
              return false;
          }
  
          login(userDn, password);
  
          return true;
      }
  
      /**
       * <p>
       * Login the user.
       * </p>
       * 
       * @param userDn The user.
       * @param password The passord.
       * @throws NamingException Throws a {@link NamingException}.
       */
      private void login(final String userDn, final String password) throws NamingException
      {
          validateDn(userDn);
          validatePassword(password);
          bindToServer(userDn, password);
  
          ctx.getResponseControls();
      }
  
      /**
       * <p>
       * Get the password.
       * </p>
       * 
       * @param results The {@link NamingEnumeration}.
       * @param uid The uid.
       * @return The password as an array of char.
       * @throws NamingException Throws a {@link NamingException}.
       */
      private char[] getPassword(final NamingEnumeration results, final String uid) throws NamingException
      {
          if (!results.hasMore())
          {
              throw new NamingException("Could not find any user with uid[" + uid + "]");
          }
  
          Attributes userAttributes = getFirstUser(results);
  
          return convertRawPassword(getAttribute(PASSWORD_ATTR_NAME, userAttributes));
      }
  
      /**
       * <p>
       * Get the attribute.
       * </p>
       * 
       * @param attributeName The attribute name.
       * @param userAttributes The user {@link Attributes}.
       * @return The {@link Attribute}
       * @throws NamingException Throws a {@link NamingException}.
       */
      private Attribute getAttribute(String attributeName, Attributes userAttributes) throws NamingException
      {
          for (NamingEnumeration ae = userAttributes.getAll(); ae.hasMore();)
          {
              Attribute attr = (Attribute) ae.next();
  
              if (attr.getID().equals(attributeName))
              {
                  return attr;
              }
          }
  
          return null;
  
      }
  
      /**
       * <p>
       * This method converts an ascii password to a char array. It needs to be
       * improved to do proper unicode conversion.
       * </p>
       * 
       * @param The {@link Attribute}.  
       */
      private char[] convertRawPassword(Attribute attr) throws NamingException
      {
          byte[] rawPass = (byte[]) attr.getAll().next();
          char[] charPass = new char[rawPass.length];
  
          for (int i = 0; i < rawPass.length; i++)
          {
              LOG.debug(new String("password byte[" + i + "]:" + rawPass[i]));
  
              Byte passByte = new Byte(rawPass[i]);
  
              LOG.debug("password byte[" + i + "] short value:" + passByte.shortValue());
              charPass[i] = (char) rawPass[i]; //I know I lose the
  
              // sign and this is only
              // good for ascii text.
              LOG.debug("passchar char[" + i + "]:" + charPass[i]);
          }
  
          return charPass;
      }
  
      /**
       * <p>
       * Gets the first matching user.
       * </p>
       * 
       * @param results The results to find the user in.
       * @return The {@param Attributes}.
       * @throws NamingException Throws a {@link NamingException}.
       */
      private Attributes getFirstUser(NamingEnumeration results) throws NamingException
      {
          SearchResult result = (SearchResult) results.next();
          Attributes answer = result.getAttributes();
  
          return answer;
      }
  
      /**
       * <p>
       * Search by explicit uid.
       * </p>
       * 
       * @param uid The uid.
       * @param cons The {@link SearchControls}.
       * @return The {@link NamingEnumeration}. 
       * @throws NamingException Throws a {@link NamingEnumeration}
       */
      private NamingEnumeration searchByExplicitUid(final String uid, SearchControls cons) throws NamingException
      {
          NamingEnumeration results = ((DirContext) ctx).search("", "uid=" + uid, cons);
  
          return results;
      }
  }
  
  
  1.1                  jakarta-jetspeed-2/components/security/src/java/org/apache/jetspeed/security/spi/impl/ldap/LdapUserCredentialDao.java
  
  Index: LdapUserCredentialDao.java
  ===================================================================
  /* Copyright 2004 Apache Software Foundation
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.jetspeed.security.spi.impl.ldap;
  
  import org.apache.jetspeed.security.SecurityException;
  
  /**
   * <p>
   * User credential dao.
   * </p>
   * 
   * @author <a href="mailto:mike.long@dataline.com">Mike Long </a>
   */
  public interface LdapUserCredentialDao extends LdapUserDao
  {
      /**
       * <p>
       * Updates the password for the specified user.
       * </p>
       * 
       * @param uid The uid.
       * @param password The password.
       * @throws SecurityException A {@link SecurityException}.
       */
      public abstract void changePassword(final String uid, final String password) throws SecurityException;
  
      /**
       * <p>
       * Looks up the user by the UID attribute. If this lookup succeeds, this
       * method then attempts to authenticate the user using the password,
       * throwing an AuthenticationException if the password is incorrect or an
       * OperationNotSupportedException if the password is empty.
       * </p>
       * 
       * @param uid The uid.
       * @param password The password.
       * @throws SecurityException A {@link SecurityException}.
       */
      public abstract boolean authenticate(final String uid, final String password) throws SecurityException;
  
      /**
       * @param uid The uid.
       * @return The password.
       *@throws SecurityException A {@link SecurityException}.@throws SecurityException
       */
      public abstract char[] getPassword(final String uid) throws SecurityException;
  }
  
  
  1.1                  jakarta-jetspeed-2/components/security/src/java/org/apache/jetspeed/security/spi/impl/ldap/LdapUserSecurityDaoImpl.java
  
  Index: LdapUserSecurityDaoImpl.java
  ===================================================================
  /*
   * Copyright 2000-2001,2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.jetspeed.security.spi.impl.ldap;
  
  import java.security.Principal;
  import java.util.ArrayList;
  import java.util.Collection;
  
  import javax.naming.Name;
  import javax.naming.NameParser;
  import javax.naming.NamingEnumeration;
  import javax.naming.NamingException;
  import javax.naming.directory.Attribute;
  import javax.naming.directory.Attributes;
  import javax.naming.directory.BasicAttribute;
  import javax.naming.directory.BasicAttributes;
  import javax.naming.directory.DirContext;
  import javax.naming.directory.SearchControls;
  import javax.naming.directory.SearchResult;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.jetspeed.security.SecurityException;
  import org.apache.jetspeed.security.impl.UserPrincipalImpl;
  
  /**
   * @see org.apache.jetspeed.security.spi.impl.ldap.LdapUserSecurityDao
   * @author <a href="mailto:mike.long@dataline.com">Mike Long </a>
   */
  public class LdapUserSecurityDaoImpl extends AbstractLdapDao implements LdapUserSecurityDao
  {
      /** The logger. */
      private static final Log LOG = LogFactory.getLog(LdapUserSecurityDaoImpl.class);
  
      /** The uid attribute name. */
      private static final String UID_ATTR_NAME = "uid";
  
      /**
       * <p>
       * Default constructor.
       * </p>
       */
      public LdapUserSecurityDaoImpl()
      {
          super();
      }
      
      /**
       * <p>
       * Initializes the dao.
       * </p>
       * 
       * @param ldapServerName The server name.
       * @param rootDn The root domain.
       * @param rootPassword The root password.
       * @param rootContext The root context.
       * @param defaultDnSuffix The default suffix.
       */
      public LdapUserSecurityDaoImpl(String ldapServerName, String rootDn, String rootPassword, String rootContext,
              String defaultDnSuffix)
      {
          super(ldapServerName, rootDn, rootPassword, rootContext, defaultDnSuffix);
      }
      
      /**
       * @see org.apache.jetspeed.security.spi.impl.ldap.LdapUserSecurityDao#create(java.lang.String)
       */
      public void create(final String uid) throws SecurityException
      {
          Attributes attrs = new BasicAttributes(true);
          BasicAttribute classes = new BasicAttribute("objectclass");
  
          classes.add("top");
          classes.add("person");
          classes.add("uidObject");
          classes.add("organizationalPerson");
          classes.add("inetorgperson");
          attrs.put(classes);
          attrs.put("cn", uid);
          attrs.put("uid", uid);
          attrs.put("sn", uid);
  
          try
          {
              ctx.createSubcontext("uid=" + uid + this.defaultDnSuffix, attrs);
          }
          catch (NamingException e)
          {
              throw new SecurityException(e);
          }
      }
  
      /**
       * @see org.apache.jetspeed.security.spi.impl.ldap.LdapUserSecurityDao#delete(java.lang.String)
       */
      public void delete(final String uid) throws SecurityException
      {
          String dn = lookupByUid(uid);
  
          if (dn == null)
          {
              return;
          }
  
          String rdn;
          try
          {
              rdn = getSubcontextName(dn);
              ctx.destroySubcontext(rdn);
          }
          catch (NamingException e)
          {
              throw new SecurityException(e);
          }
      }
  
      /**
       * @see org.apache.jetspeed.security.spi.impl.ldap.LdapUserSecurityDao#find(java.lang.String)
       */
      public Principal[] find(final String uid) throws SecurityException
      {
          try
          {
              bindToServer(this.rootDn, this.rootPassword);
  
              SearchControls cons = setSearchControls();
              NamingEnumeration searchResults = searchByWildcardedUid(uid, cons);
              Collection userPrincipals = new ArrayList();
  
              enumerateOverSearchResults(searchResults, userPrincipals);
  
              return convertPrincipalListToArray(userPrincipals);
          }
          catch (NamingException e)
          {
              throw new SecurityException(e);
          }
      }
  
      /**
       * <p>
       * Converts a list of principals to an array of principals.
       * </p>
       * 
       * @param userPrincipals The list of principals.
       * @return The array of principals.
       */
      private Principal[] convertPrincipalListToArray(Collection userPrincipals)
      {
          return (Principal[]) userPrincipals.toArray(new Principal[userPrincipals.size()]);
      }
  
      /**
       * <p>
       * Build the user principal by enumerating through the search results.
       * </p>
       * 
       * @param searchResults The {@link NamingEnumeration} of results.
       * @param userPrincipals The collection of user principals.
       * @throws NamingException Throws a {@link NamingException}.
       */
      private void enumerateOverSearchResults(NamingEnumeration searchResults, Collection userPrincipals)
              throws NamingException
      {
          while (searchResults.hasMore())
          {
              SearchResult searchResult = (SearchResult) searchResults.next();
  
              buildUserPrincipal(userPrincipals, searchResult);
          }
      }
  
      /**
       * @param userPrincipals The collection of user principals.
       * @param searchResult The {@link SearchResult}
       * @throws NamingException Throws a {@link NamingException}.
       */
      private void buildUserPrincipal(Collection userPrincipals, SearchResult searchResult) throws NamingException
      {
          if (searchResult.getObject() instanceof DirContext)
          {
              Attributes atts = searchResult.getAttributes();
  
              String uid = (String) getAttribute(UID_ATTR_NAME, atts).getAll().next();
              Principal userPrincipal = new UserPrincipalImpl(uid);
  
              userPrincipals.add(userPrincipal);
          }
      }
  
      /**
       * @param attributeName The attribute name.
       * @param userAttributes The user {@link Attributes}.
       * @return The {@link Attribute}.
       * @throws NamingException Throws a {@link NamingException}.
       */
      private Attribute getAttribute(String attributeName, Attributes userAttributes) throws NamingException
      {
          for (NamingEnumeration ae = userAttributes.getAll(); ae.hasMore();)
          {
              Attribute attr = (Attribute) ae.next();
  
              if (attr.getID().equals(attributeName))
              {
                  return attr;
              }
          }
          return null;
      }
  
      /**
       * @param dn
       * @return
       * @throws NamingException
       */
      private String getSubcontextName(final String dn) throws NamingException
      {
          NameParser parser = ctx.getNameParser("");
          Name name = parser.parse(dn);
          String rootStr = ctx.getNameInNamespace();
          Name root = parser.parse(rootStr);
  
          if (name.startsWith(root))
          {
              Name rname = name.getSuffix(root.size());
  
              return rname.toString();
          }
  
          return dn;
      }
  }
  
  
  1.1                  jakarta-jetspeed-2/components/security/src/java/org/apache/jetspeed/security/spi/impl/ldap/LdapUserDao.java
  
  Index: LdapUserDao.java
  ===================================================================
  /*
   * Copyright 2000-2001,2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.jetspeed.security.spi.impl.ldap;
  
  import org.apache.jetspeed.security.SecurityException;
  
  /**
   * <p>
   * Dao for querying users in ldap.
   * </p>
   * 
   * @author <a href="mailto:mike.long@dataline.com">Mike Long </a>
   */
  public interface LdapUserDao
  {
      /**
       * <p>
       * Searches the LDAP server for the user with the specified userid (uid
       * attribute).
       * </p>
       * 
       * @return the user's DN
       */
      String lookupByUid(final String uid) throws SecurityException;
  
  }
  
  
  1.1                  jakarta-jetspeed-2/components/security/src/java/org/apache/jetspeed/security/spi/impl/ldap/AbstractLdapDao.java
  
  Index: AbstractLdapDao.java
  ===================================================================
  /* Copyright 2004 Apache Software Foundation
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.jetspeed.security.spi.impl.ldap;
  
  import java.util.Properties;
  
  import javax.naming.Context;
  import javax.naming.NamingEnumeration;
  import javax.naming.NamingException;
  import javax.naming.directory.DirContext;
  import javax.naming.directory.SearchControls;
  import javax.naming.directory.SearchResult;
  import javax.naming.ldap.InitialLdapContext;
  import javax.naming.ldap.LdapContext;
  
  import org.apache.commons.lang.StringUtils;
  import org.apache.jetspeed.security.SecurityException;
  
  /**
   * <p>
   * Abstract ldap dao.
   * </p>
   * 
   * @author <a href="mailto:mike.long@dataline.com">Mike Long </a>
   */
  public abstract class AbstractLdapDao
  {
      /** The ldap server name. */
      private String ldapServerName = null;
  
      /** The root domain. */
      protected String rootDn = null;
  
      /** The root password. */
      protected String rootPassword = null;
  
      /** The root context. */
      protected String rootContext = null;
  
      /** The default suffix. */
      protected String defaultDnSuffix = null;
  
      /** Reference to remote server context */
      protected LdapContext ctx;
  
      /**
       * <p>
       * Default constructor.
       * </p>
       */
      public AbstractLdapDao()
      {
      }
      
      /**
       * <p>
       * Initializes the dao.
       * </p>
       * 
       * @param ldapServerName The server name.
       * @param rootDn The root domain.
       * @param rootPassword The root password.
       * @param rootContext The root context.
       * @param defaultDnSuffix The default suffix.
       */
      public AbstractLdapDao(String ldapServerName, String rootDn, String rootPassword, String rootContext,
              String defaultDnSuffix)
      {
          this.ldapServerName = ldapServerName;
          this.rootDn = rootDn;
          this.rootPassword = rootPassword;
          this.rootContext = rootContext;
          this.defaultDnSuffix = defaultDnSuffix;
      }
      
      /**
       * <p>
       * Binds to the ldap server.
       * </p>
       * 
       * @param userDn
       * @param password
       * @throws NamingException
       */
      protected void bindToServer(final String userDn, final String password) throws NamingException
      {
          validateDn(userDn);
          validatePassword(password);
  
          Properties env = new Properties();
  
          env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
          env.put(Context.PROVIDER_URL, "ldap://" + this.ldapServerName + "/" + this.rootContext);
          env.put(Context.SECURITY_PRINCIPAL, userDn);
          env.put(Context.SECURITY_CREDENTIALS, password);
          env.put(Context.SECURITY_AUTHENTICATION, "simple");
          ctx = new InitialLdapContext(env, null);
      }
  
      /**
       * <p>
       * Validate the domain name.
       * </p>
       * 
       * @param dn The domain name.
       */
      protected void validateDn(final String dn)
      {
          if (StringUtils.isEmpty(dn))
          {
              throw new IllegalArgumentException("The dn cannot be null or empty");
          }
      }
  
      /**
       * <p>
       * Valiate the users password.
       * </p>
       * 
       * @param userDn The user.
       */
      protected void validatePassword(final String password)
      {
          if (StringUtils.isEmpty(password))
          {
              throw new IllegalArgumentException("The password cannot be null or empty");
          }
      }
  
      /**
       * @return The factors that determine the scope of the search and what gets
       *         returned as a result of the search.
       */
      protected SearchControls setSearchControls()
      {
          SearchControls controls = new SearchControls();
  
          controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
          controls.setReturningObjFlag(true);
  
          return controls;
      }
  
      /**
       * <p>
       * Searches the LDAP server for the user with the specified userid (uid
       * attribute).
       * </p>
       * 
       * @return the user's DN
       */
      public String lookupByUid(final String uid) throws SecurityException
      {
          validateUid(uid);
  
          try
          {
              bindToServer(this.rootDn, this.rootPassword);
  
              SearchControls cons = setSearchControls();
              NamingEnumeration searchResults = searchByWildcardedUid(uid, cons);
  
              return getFirstDnForUid(searchResults);
          }
          catch (NamingException e)
          {
              throw new SecurityException(e);
          }
      }
  
      /**
       * <p>
       * Gets the first matching user for the given uid.
       * </p>
       * 
       * @param searchResults The {@link NamingEnumeration}.
       * @return the user's DN of the first use in the list. Null if no users were
       *         found.
       * @throws NamingException Throws a {@link NamingException}.
       */
      private String getFirstDnForUid(NamingEnumeration searchResults) throws NamingException
      {
          String userDn = null;
          while (searchResults.hasMore())
          {
              SearchResult searchResult = (SearchResult) searchResults.next();
  
              if (searchResult.getObject() instanceof DirContext)
              {
                  DirContext userEntry = (DirContext) searchResult.getObject();
                  userDn = userEntry.getNameInNamespace();
              }
          }
          return userDn;
      }
  
      /**
       * <p>
       * Validate the uid.
       * </p>
       * 
       * @param uid The uid.
       */
      protected void validateUid(String uid)
      {
          if (StringUtils.isEmpty(uid) || uid.matches("\\(\\[\\{\\^\\$\\|\\)\\?\\*\\+\\.\\\\"))
          {
              throw new IllegalArgumentException(
                      "The uid cannot contain any regular expression meta-characters or be null or be empty ");
          }
      }
  
      /**
       * <p>
       * Search uid by wild card.
       * </p>
       * 
       * @param filter The filter.
       * @param cons The {@link SearchControls}
       * @return The {@link NamingEnumeration}
       * @throws NamingException Throws a {@link NamingEnumeration}.
       */
      protected NamingEnumeration searchByWildcardedUid(final String filter, SearchControls cons) throws NamingException
      {
          NamingEnumeration searchResults = ((DirContext) ctx).search("", "uid="
                  + (StringUtils.isEmpty(filter) ? "*" : filter), cons);
  
          return searchResults;
      }
  }
  
  
  1.1                  jakarta-jetspeed-2/components/security/src/test/org/apache/jetspeed/security/spi/ldap/AbstractLdapTest.java
  
  Index: AbstractLdapTest.java
  ===================================================================
  /* Copyright 2004 Apache Software Foundation
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.jetspeed.security.spi.ldap;
  
  import junit.framework.TestCase;
  
  import org.apache.jetspeed.security.UserPrincipal;
  import org.apache.jetspeed.security.impl.UserPrincipalImpl;
  import org.apache.jetspeed.security.spi.CredentialHandler;
  import org.apache.jetspeed.security.spi.UserSecurityHandler;
  import org.apache.jetspeed.security.spi.impl.LdapCredentialHandler;
  import org.apache.jetspeed.security.spi.impl.LdapUserSecurityHandler;
  import org.apache.jetspeed.security.spi.impl.ldap.LdapUserCredentialDao;
  import org.apache.jetspeed.security.spi.impl.ldap.LdapUserCredentialDaoImpl;
  import org.apache.jetspeed.security.spi.impl.ldap.LdapUserSecurityDao;
  import org.apache.jetspeed.security.spi.impl.ldap.LdapUserSecurityDaoImpl;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.IOException;
  import java.util.Properties;
  import java.util.Random;
  
  /**
   * <p>
   * Abstract test case for LDAP providers.
   * </p>
   * 
   * @author <a href="mailto:mike.long@dataline.com">Mike Long </a>
   */
  public abstract class AbstractLdapTest extends TestCase
  {
      /** The ldap properties. */
      private static Properties props = null;
  
      /** The {@link UserSecurityHandler}. */
      UserSecurityHandler userHandler;
  
      /** The {@link CredentialHandler}. */
      CredentialHandler crHandler;
  
      /** The {@link UserPrincipal}. */
      UserPrincipal prin;
      
      /** Random seed. */
      Random rand = new Random(System.currentTimeMillis());
  
      /** The test uid. */
      protected String uid;
  
      /** The test password. */
      protected String password = "fred";
  
      /**
       * @see junit.framework.TestCase#setUp()
       */
      protected void setUp() throws Exception
      {
          super.setUp();
          initializeConfiguration();
          LdapUserCredentialDao credDao = new LdapUserCredentialDaoImpl(props.getProperty("org.apache.jetspeed.ldap.ldapServerName"),
                  props.getProperty("org.apache.jetspeed.ldap.rootDn"), props.getProperty("org.apache.jetspeed.ldap.rootPassword"),
                  props.getProperty("org.apache.jetspeed.ldap.rootContext"), props.getProperty("org.apache.jetspeed.ldap.defaultDnSuffix"));
          
          LdapUserSecurityDao userSecDao = new LdapUserSecurityDaoImpl(props.getProperty("org.apache.jetspeed.ldap.ldapServerName"),
                  props.getProperty("org.apache.jetspeed.ldap.rootDn"), props.getProperty("org.apache.jetspeed.ldap.rootPassword"),
                  props.getProperty("org.apache.jetspeed.ldap.rootContext"), props.getProperty("org.apache.jetspeed.ldap.defaultDnSuffix"));    
          
          userHandler = new LdapUserSecurityHandler(userSecDao);
          crHandler = new LdapCredentialHandler(credDao);
          uid = Integer.toString(rand.nextInt());
          prin = new UserPrincipalImpl(uid);
          userHandler.addUserPrincipal(prin);
          crHandler.setPassword(uid, "", password);
      }
  
      /**
       * @see junit.framework.TestCase#tearDown()
       */
      protected void tearDown() throws Exception
      {
          super.tearDown();
  
          if (prin != null)
          {
              userHandler.removeUserPrincipal(prin);
          }
      }
      
      /**
       * <p>
       * Init ldap config.
       * </p>
       */
      protected static void initializeConfiguration()
      {
          String testPropsPath = "./etc/ldap.properties";
          try
          {
              File testFile = new File(testPropsPath);
              if (testFile.exists())
              {
                  FileInputStream is = new FileInputStream(testPropsPath);
                  props = new Properties();
                  props.load(is);
              }
          }
          catch (IOException e)
          {
              e.printStackTrace();
          }
      }
  }
  
  
  1.1                  jakarta-jetspeed-2/components/security/src/test/org/apache/jetspeed/security/spi/ldap/TestLdapCredentialHandler.java
  
  Index: TestLdapCredentialHandler.java
  ===================================================================
  /*
   * Copyright 2000-2001,2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.jetspeed.security.spi.ldap;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.jetspeed.security.PasswordCredential;
  import org.apache.jetspeed.security.SecurityException;
  import org.apache.jetspeed.security.spi.impl.LdapCredentialHandler;
  
  import java.util.Set;
  
  /**
   * <p>
   * Test {@link LdapCredentialHandler} implementation of the SPI <code>CredentialHandler</code>.
   * </p>
   * 
   * @author <a href="mailto:mike.long@dataline.com">Mike Long </a>  
   */
  public class TestLdapCredentialHandler extends AbstractLdapTest
  {
      /** The logger. */
      private static final Log log = LogFactory.getLog(TestLdapCredentialHandler.class);
  
      /**
       * @see junit.framework.TestCase#setUp()
       */
      protected void setUp() throws Exception
      {
          super.setUp();
          crHandler = new LdapCredentialHandler();
      }
  
      /**
       * <p>
       * Test <code>getPrivateCredentials</code>
       * </p>
       * 
       * @throws SecurityException A {@link SecurityException}.
       */
      public void testGetPrivateCredentials() throws SecurityException
      {
          Set credentials = crHandler.getPrivateCredentials(uid);
  
          assertTrue("getPrivateCredentials found no credentials for user:" + uid, credentials.size() > 0);
  
          PasswordCredential cred = (PasswordCredential) credentials.iterator().next();
  
          assertEquals(password, String.valueOf(cred.getPassword()));
      }
  
      /**
       * <p>
       * Test <code>getPrivateCredentials</code> for a user that does not exist.
       * </p>
       * 
       * @throws SecurityException A {@link SecurityException}.
       */
      public void testGetPrivateCredentialsForNonExistantUser() throws SecurityException
      {
          String nonExistantUser = Integer.toString(rand.nextInt());
          Set credentials = crHandler.getPrivateCredentials(nonExistantUser);
  
          assertTrue("getPrivateCredentials should not have found credentials for user:" + nonExistantUser, credentials
                  .isEmpty());
      }
  
      /**
       * <p>
       * Test <code>setPassword</code>.
       * </p>
       * 
       * @throws SecurityException A {@link SecurityException}.
       */
      public void testSetPassword() throws SecurityException
      {
          crHandler.setPassword(uid, password, "freddie");
          assertTrue("Failed to change the password.", crHandler.authenticate(uid, "freddie"));
          crHandler.setPassword(uid, "freddie", password);
      }
  
      /**
       * <p>
       * Test <code>setPassword</code> with null password.
       * </p>
       * 
       * @throws SecurityException A {@link SecurityException}.
       */
      public void testVerifyNullSetPassword() throws SecurityException
      {
          crHandler.setPassword(uid, null, password);
      }
  
      /**
       * <p>
       * Test <code>authenticate</code> with correct login.
       * </p>
       * 
       * @throws SecurityException A {@link SecurityException}.
       */
      public void testGoodLogin() throws SecurityException
      {
          assertTrue("The login failed for user.", crHandler.authenticate(uid, password));
      }
  
      /**
       * <p>
       * Test <code>authenticate</code> with no password.
       * </p>
       * 
       * @throws SecurityException A {@link SecurityException}.
       */
      public void testCannotAuthenticateWithNoPassword()
      {
          try
          {
              crHandler.authenticate(uid, "");
              fail("Should have thrown a SecurityException.");
          }
          catch (Exception e)
          {
              assertTrue("Should have thrown an SecurityException but threw:" + e, e instanceof SecurityException);
          }
      }
  
      /**
       * <p>
       * Test <code>authenticate</code> with bad uid.
       * </p>
       * 
       * @throws SecurityException A {@link SecurityException}.
       */
      public void testBadUID() throws SecurityException
      {
          String nonExistantUser = Integer.toString(rand.nextInt());
  
          assertFalse("The login should have failed for user.", crHandler.authenticate(nonExistantUser, password));
      }
  
      /**
       * <p>
       * Test <code>authenticate</code> with bad password.
       * </p>
       * 
       * @throws SecurityException A {@link SecurityException}.
       */
      public void testBadPassword()
      {
          try
          {
              crHandler.authenticate(uid, password + "123");
              fail("Should have thrown an SecurityException.");
          }
          catch (Exception e)
          {
              assertTrue("Should have thrown an SecurityException.", e instanceof SecurityException);
          }
      }
  }
  
  
  1.1                  jakarta-jetspeed-2/components/security/src/test/org/apache/jetspeed/security/spi/ldap/TestLdapUserSecurityHandler.java
  
  Index: TestLdapUserSecurityHandler.java
  ===================================================================
  /*
   * Copyright 2000-2001,2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.jetspeed.security.spi.ldap;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.jetspeed.security.SecurityException;
  import org.apache.jetspeed.security.UserPrincipal;
  import org.apache.jetspeed.security.impl.UserPrincipalImpl;
  
  import java.security.Principal;
  
  import java.util.List;
  
  /**
   * <p>
   * LdapServerTest - This class tests the LdapServer. It assumes that the
   * following three inetOrgPerson objects exist:
   * 
   * uid:cbrewton password:maddie uid:dlong, password: uid:mlong, password:maddie
   * 
   * </p>
   * 
   * @author <a href="mailto:mike.long@dataline.com">Mike Long </a>
   *  
   */
  public class TestLdapUserSecurityHandler extends AbstractLdapTest
  {
      /** The logger. */
      private static final Log log = LogFactory.getLog(TestLdapUserSecurityHandler.class);
  
      /**
       * <p>
       * Test <code>isUserPrincipal</code>.
       * </p>
       */
      public void testUserIsPrincipal()
      {
          assertTrue("User is not principal.", userHandler.isUserPrincipal(uid));
      }
  
      /**
       * <p>
       * Test <code>isUserPrincipal</code>.
       * </p>
       */
      public void testUserIsNotPrincipal()
      {
          assertFalse("User is principal and should not be.", userHandler.isUserPrincipal(Integer
                  .toString(rand.nextInt()).toString()));
      }
  
      /**
       * <p>
       * Test <code>addUserPrincipal</code> when the user principal already exists.
       * </p>
       */
      public void testAddDuplicateUserPrincipal()
      {
          try
          {
              userHandler.addUserPrincipal(new UserPrincipalImpl(uid));
              fail("Adding an already existant user should have thrown a SecurityException.");
          }
          catch (Exception e)
          {
              assertTrue("Adding an already existant user should have thrown a SecurityException.",
                      e instanceof SecurityException);
          }
      }
  
      /**
       * <p>
       * Test <code>addUserPrincipal</code>.
       * </p>
       * 
       * @throws SecurityException A {@link SecurityException}.
       */
      public void testAddUserPrincipal() throws SecurityException
      {
          assertTrue("User not found.", userHandler.getUserPrincipal(uid) != null);
      }
  
      /**
       * <p>
       * Test <code>removeUserPrincipal</code> where the user principal exists.
       * </p>
       * 
       * @throws SecurityException A {@link SecurityException}.
       */
      public void testRemoveExistantUserPrincipal() throws SecurityException
      {
          userHandler.removeUserPrincipal(prin);
          assertTrue("User was found and should have been removed.", userHandler.getUserPrincipal(uid) == null);
      }
  
      /**
       * <p>
       * Test <code>removeUserPrincipal</code> where the user principal does not exist.
       * </p>
       * 
       * @throws SecurityException A {@link SecurityException}.
       */
      public void testRemoveNonExistantUserPrincipal() throws SecurityException
      {
          String localUid = Integer.toString(rand.nextInt()).toString();
          UserPrincipal localPrin = new UserPrincipalImpl(localUid);
  
          userHandler.removeUserPrincipal(localPrin);
      }
  
      /**
       * <p>
       * Test <code>getUserPrincipals</code>.
       * </p>
       * 
       * @throws SecurityException A {@link SecurityException}.
       */
      public void testGetUserPrincipals() throws SecurityException
      {
          assertTrue("getUserPrincipals should have returned more than one user.", userHandler.getUserPrincipals("*")
                  .size() > 1);
  
          List users = userHandler.getUserPrincipals(uid);
  
          assertTrue("getUserPrincipals should have returned one user.", users.size() == 1);
          assertTrue("List should have consisted of Principal objects.", users.get(0) instanceof Principal);
  
          String localUid = Integer.toString(rand.nextInt()).toString();
  
          assertTrue("getUserPrincipals should not have found any users with the specified filter.", userHandler
                  .getUserPrincipals(localUid).isEmpty());
      }
  }
  
  
  1.1                  jakarta-jetspeed-2/components/security/src/test/org/apache/jetspeed/security/spi/ldap/TestLdapUserCredentialDao.java
  
  Index: TestLdapUserCredentialDao.java
  ===================================================================
  /*
   * Copyright 2000-2001,2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.jetspeed.security.spi.ldap;
  
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  
  import javax.naming.NamingException;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.jetspeed.security.SecurityException;
  import org.apache.jetspeed.security.spi.impl.ldap.LdapUserCredentialDao;
  import org.apache.jetspeed.security.spi.impl.ldap.LdapUserCredentialDaoImpl;
  import org.apache.jetspeed.security.spi.ldap.AbstractLdapTest;
  
  /**
   * <p>
   * Test the {@link LdapUserCredentialDao}.
   * </p>
   * 
   * @author <a href="mailto:mike.long@dataline.com">Mike Long </a>
   *  
   */
  public class TestLdapUserCredentialDao extends AbstractLdapTest
  {
      /** Configuration for the number of threads performing login. */
      private static int NUMBER_OF_LOGIN_THREADS = 5;
  
      /** Configuration for the number of login per thread. */
      private static int NUMBER_OF_LOGINS_PER_THREAD = 10;
  
      /** Map of login threads. */
      private static Map loginThreads = new HashMap();
  
      /** The logger. */
      private static final Log log = LogFactory.getLog(TestLdapUserCredentialDao.class);
  
      /** The {@link LdapUserCredentialDao}. */
      private LdapUserCredentialDao ldap;
  
      /**
       * @see junit.framework.TestCase#setUp()
       */
      protected void setUp() throws Exception
      {
          super.setUp();
          ldap = new LdapUserCredentialDaoImpl();
      }
  
      /**
       * <p>
       * Test <code>authenticate</code> with correct login.
       * </p>
       * 
       * @throws SecurityException A {@link SecurityException}.
       */
      public void testGoodLogin() throws SecurityException
      {
          assertTrue("The login failed for user.", ldap.authenticate(uid, password));
      }
  
      /**
       * <p>
       * Test that the uid does not contain any of the following character:
       * <code>([{\^$|)?*+.</code>
       * </p>
       */
      public void testRegularExpessionInUid()
      {
          // ([{\^$|)?*+.
          verifyRegularExpressionFails("(");
          verifyRegularExpressionFails("[");
          verifyRegularExpressionFails("{");
          verifyRegularExpressionFails("\\");
          verifyRegularExpressionFails("^");
          verifyRegularExpressionFails("$");
          verifyRegularExpressionFails("|");
          verifyRegularExpressionFails(")");
          verifyRegularExpressionFails("?");
          verifyRegularExpressionFails("*");
          verifyRegularExpressionFails("+");
          verifyRegularExpressionFails(".");
      }
  
      /**
       * <p>
       * Test <code>authenticate</code> with incorrect character in uid.
       * </p>
       */
      private void verifyRegularExpressionFails(String metaCharacter)
      {
          try
          {
              ldap.authenticate(uid + metaCharacter, password);
              fail("Should have thrown an IllegalArgumentException because the uid contained a regular expression meta-character.");
          }
          catch (Exception e)
          {
              assertTrue(
                      "Should have thrown an IllegalArgumentException  because the uid contained a regular expression meta-character.",
                      e instanceof IllegalArgumentException);
          }
      }
  
      /**
       * <p>
       * Test <code>authenticate</code> with no password.
       * </p>
       */
      public void testCannotAuthenticateWithNoPassword()
      {
          try
          {
              ldap.authenticate(uid, "");
              fail("Should have thrown an SecurityException.");
          }
          catch (Exception e)
          {
              log.debug(e);
              assertTrue("Should have thrown an SecurityException.", e instanceof SecurityException);
          }
  
          try
          {
              ldap.authenticate(uid, null);
              fail("Should have thrown an SecurityException.");
          }
          catch (Exception e)
          {
              assertTrue("Should have thrown an SecurityException." + e, e instanceof SecurityException);
          }
      }
  
      /**
       * <p>
       * Test <code>authenticate</code> with bad uid.
       * </p>
       * 
       * @throws SecurityException A {@link SecurityException}.
       */
      public void testBadUID() throws SecurityException
      {
          assertFalse("The login should have failed for user.", ldap.authenticate(uid + "123", password));
      }
  
      /**
       * <p>
       * Test <code>authenticate</code> with bad password.
       * </p>
       * 
       * @throws NamingException A {@link NamingException}.
       */
      public void testBadPassword() throws NamingException
      {
          try
          {
              ldap.authenticate(uid, password + "123");
              fail("Should have thrown a SecurityException.");
          }
          catch (Exception e)
          {
              assertTrue("Should have thrown a SecurityException.", e instanceof SecurityException);
          }
      }
  
      /**
       * <p>
       * Test <code>authenticate</code> with concurrent logins.
       * </p>
       * 
       * @throws InterruptedException A {@link InterruptedException}.
       */
      public void testConcurrentLogins() throws InterruptedException
      {
          for (int i = 0; i < NUMBER_OF_LOGIN_THREADS; i++)
          {
              LoginThread thread = new LoginThread();
  
              thread.start();
          }
  
          Thread.sleep(6000);
          assertTrue("Not all login threads completed.", loginThreads.size() == NUMBER_OF_LOGIN_THREADS);
          assertTrue("Not all login threads successfully ran all their logins().", allLoginThreadsCompletedTheirLogins());
          assertFalse("An exception was thrown by a login thread. This means there is a concurrency problem.",
                  exceptionThrownByLogin());
      }
  
      /**
       * <p>
       * Gets the exception thrown by the login operation.
       * </p>
       */
      private boolean exceptionThrownByLogin()
      {
          boolean exceptionThrown = false;
          Iterator loginThreadStatuses = loginThreads.values().iterator();
  
          while (loginThreadStatuses.hasNext())
          {
              LoginThreadStatus status = (LoginThreadStatus) loginThreadStatuses.next();
  
              if (status.isSomeExceptionThrown())
              {
                  exceptionThrown = true;
              }
          }
  
          return exceptionThrown;
      }
  
      /**
       * <p>
       * Whether all login thread completed their login.
       * </p>
       */
      private boolean allLoginThreadsCompletedTheirLogins()
      {
          boolean allThreadsCompletedTheirLogins = true;
          Iterator loginThreadStatuses = loginThreads.values().iterator();
  
          while (loginThreadStatuses.hasNext())
          {
              LoginThreadStatus status = (LoginThreadStatus) loginThreadStatuses.next();
  
              if (status.getNumberOfSuccessfulLogins() < NUMBER_OF_LOGINS_PER_THREAD)
              {
                  allThreadsCompletedTheirLogins = false;
              }
          }
  
          return allThreadsCompletedTheirLogins;
      }
  
      /**
       * <p>
       * Login threads.
       * </p>
       */
      private class LoginThread extends Thread
      {
          /** The login thread status. */
          private LoginThreadStatus status = new LoginThreadStatus();
  
          /** The {@link LdapUserCredentialDao}. */
          private LdapUserCredentialDao threadLdap = new LdapUserCredentialDaoImpl();
  
          /**
           * @see java.lang.Runnable#run()
           */
          public void run()
          {
              for (int i = 0; i < NUMBER_OF_LOGINS_PER_THREAD; i++)
              {
                  try
                  {
                      assertTrue("The login failed for user.", threadLdap.authenticate(uid, password));
                      status.incrementNumberOfSuccessfulLogins();
                  }
                  catch (Exception e)
                  {
                      status.setSomeExceptionThrown(true);
                  }
              }
  
              TestLdapUserCredentialDao.loginThreads.put(this, status);
          }
      }
  }
  
  /**
   * <p>
   * The Login thread status.
   * </p>
   */
  class LoginThreadStatus
  {
      private int numberOfSuccessfulLogins;
  
      private boolean someExceptionThrown;
  
      void incrementNumberOfSuccessfulLogins()
      {
          this.numberOfSuccessfulLogins++;
      }
  
      int getNumberOfSuccessfulLogins()
      {
          return numberOfSuccessfulLogins;
      }
  
      void setSomeExceptionThrown(boolean someExceptionThrown)
      {
          this.someExceptionThrown = someExceptionThrown;
      }
  
      boolean isSomeExceptionThrown()
      {
          return someExceptionThrown;
      }
  }
  
  
  1.1                  jakarta-jetspeed-2/components/security/src/test/org/apache/jetspeed/security/spi/ldap/TestLdapUserSecurityDao.java
  
  Index: TestLdapUserSecurityDao.java
  ===================================================================
  /*
   * Copyright 2000-2001,2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.jetspeed.security.spi.ldap;
  
  import org.apache.commons.lang.StringUtils;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.jetspeed.security.SecurityException;
  import org.apache.jetspeed.security.spi.impl.ldap.LdapUserSecurityDao;
  import org.apache.jetspeed.security.spi.impl.ldap.LdapUserSecurityDaoImpl;
  import org.apache.jetspeed.security.spi.ldap.AbstractLdapTest;
  
  /**
   * <p>
   * Test the {@link LdapUserSecurityDao}.
   * </p>
   * 
   * @author <a href="mailto:mike.long@dataline.com">Mike Long </a>
   *  
   */
  public class TestLdapUserSecurityDao extends AbstractLdapTest
  {
      /** The logger. */
      private static final Log log = LogFactory.getLog(TestLdapUserSecurityDao.class);
  
      /** The {@link LdapUserSecurityDao}. */
      private LdapUserSecurityDao ldap;
  
      /**
       * @see junit.framework.TestCase#setUp()
       */
      protected void setUp() throws Exception
      {
          super.setUp();
          ldap = new LdapUserSecurityDaoImpl();
      }
  
      /**
       * <p>
       * Test <code>lookupByUid</code> with a good uid.
       * </p>
       * 
       * @throws SecurityException A {@link SecurityException}.
       */
      public void testLookupByGoodUID() throws SecurityException
      {
          assertFalse("The loookup failed for user.", StringUtils.isEmpty(ldap.lookupByUid(uid)));
      }
  
      /**
       * <p>
       * Test <code>lookupByUid</code> with a bad uid.
       * </p>
       * 
       * @throws SecurityException A {@link SecurityException}.
       */
      public void testLookupByBadUID() throws SecurityException
      {
          assertTrue("The lookup should have failed for user:" + uid + "123", StringUtils.isEmpty(ldap.lookupByUid(uid
                  + "123")));
      }
  }
  
  
  1.8       +2 -1      jakarta-jetspeed-2/xdocs/navigation.xml
  
  Index: navigation.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-jetspeed-2/xdocs/navigation.xml,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- navigation.xml	25 Jan 2005 18:04:05 -0000	1.7
  +++ navigation.xml	21 Feb 2005 21:34:46 -0000	1.8
  @@ -34,11 +34,12 @@
         <item name="Sub Projects" href="projects-overview.html"/>
       </menu>
       <menu name='Security'>        
  -      <item name="Security Overview" href="security-overview.html"/>       
  +      <item name="Security Overview" href="multiproject/jetspeed-security/index.html"/>       
         <item name="Authentication" href="authentication.html"/>
         <item name="JAAS Authorization" href="authorization.html"/>
         <item name="PSML Authorization" href="bronco.html"/>
         <item name="SPI: Providers and Handlers" href="spi.html"/>
  +      <item name="Security Services Configuration" href="multiproject/jetspeed-security/config.html"/>
         <item name="Single Sign on" href="sso.html"/>        
       </menu>
       <menu name='Portal Design'>
  
  
  
  1.1                  jakarta-jetspeed-2/components/security/etc/security-spi-ldap.xml
  
  Index: security-spi-ldap.xml
  ===================================================================
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
  <!--
  Copyright 2004 The Apache Software Foundation
  
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
  
      http://www.apache.org/licenses/LICENSE-2.0
  
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  -->
  <beans>
  
    <!-- ************** Ldap Configuration ************** -->
    <!-- Adds ldap.properties as our configuration object to support ${...} vars -->
    <!-- ${applicationRoot} is acutally set as a system property via the SpringEngine -->
    <bean id="ldapPlaceholderConfig"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
      <property name="location"><value>file:///${applicationRoot}/WEB-INF/conf/ldap.properties</value></property>
    </bean>
  
  </beans>
  
  
  
  1.1                  jakarta-jetspeed-2/components/security/etc/ldap.properties
  
  Index: ldap.properties
  ===================================================================
  # Ldap Configuration.
  org.apache.jetspeed.ldap.ldapServerName=localhost
  org.apache.jetspeed.ldap.rootDn=cn\=Manager,dc\=proto,dc\=dataline,dc\=com
  org.apache.jetspeed.ldap.rootPassword=secret
  org.apache.jetspeed.ldap.rootContext=dc\=proto,dc\=dataline,dc\=com
  org.apache.jetspeed.ldap.defaultDnSuffix=ou\=Norfolk,o\=Dataline
  
  
  
  1.1                  jakarta-jetspeed-2/components/security/etc/security-spi-ldap-atn.xml
  
  Index: security-spi-ldap-atn.xml
  ===================================================================
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
  <!--
  Copyright 2004 The Apache Software Foundation
  
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
  
      http://www.apache.org/licenses/LICENSE-2.0
  
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  -->
  <beans>
  
    <!-- ************** Security SPI Handlers ************** -->
    <!-- Security SPI: LdapUserCredentialDao -->
    <bean id="org.apache.jetspeed.security.spi.impl.ldap.LdapUserCredentialDao" 
         class="org.apache.jetspeed.security.spi.impl.ldap.LdapUserCredentialDaoImpl"
    >       
         <constructor-arg index="0"><value>${org.apache.jetspeed.ldap.ldapServerName}</value></constructor-arg>       
         <constructor-arg index="1"><value>${org.apache.jetspeed.ldap.rootDn}</value></constructor-arg>       
         <constructor-arg index="2"><value>${org.apache.jetspeed.ldap.rootPassword}</value></constructor-arg>
         <constructor-arg index="3"><value>${org.apache.jetspeed.ldap.rootContext}</value></constructor-arg>  
         <constructor-arg index="4"><value>${org.apache.jetspeed.ldap.defaultDnSuffix}</value></constructor-arg>        
    </bean>
    
    <!-- Security SPI: CredentialHandler -->
    <bean id="org.apache.jetspeed.security.spi.CredentialHandler" 
         class="org.apache.jetspeed.security.spi.impl.ldap.LdapCredentialHandler"
    >       
         <constructor-arg ><ref bean="org.apache.jetspeed.security.spi.impl.ldap.LdapUserCredentialDao"/></constructor-arg>    
    </bean>
    
    <!-- Security SPI: UserSecurityHandler -->
    <bean id="org.apache.jetspeed.security.spi.UserSecurityHandler" 
    	   class="org.apache.jetspeed.security.spi.impl.ldap.LdapUserSecurityHandler"
    >  	   
    	   <constructor-arg ><ref bean="org.apache.jetspeed.security.spi.impl.ldap.LdapUserCredentialDao"/></constructor-arg> 	   
    </bean>
  
  </beans>
  
  
  
  1.4       +105 -41   jakarta-jetspeed-2/components/security/src/java/org/apache/jetspeed/security/spi/impl/LdapCredentialHandler.java
  
  Index: LdapCredentialHandler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-jetspeed-2/components/security/src/java/org/apache/jetspeed/security/spi/impl/LdapCredentialHandler.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- LdapCredentialHandler.java	8 Nov 2004 03:23:35 -0000	1.3
  +++ LdapCredentialHandler.java	21 Feb 2005 21:34:47 -0000	1.4
  @@ -1,103 +1,167 @@
   /* Copyright 2004 Apache Software Foundation
  -*
  -* Licensed under the Apache License, Version 2.0 (the "License");
  -* you may not use this file except in compliance with the License.
  -* You may obtain a copy of the License at
  -*
  -*     http://www.apache.org/licenses/LICENSE-2.0
  -*
  -* Unless required by applicable law or agreed to in writing, software
  -* distributed under the License is distributed on an "AS IS" BASIS,
  -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  -* See the License for the specific language governing permissions and
  -* limitations under the License.
  -*/
  + *
  + * Licensed under the Apache License, Version 2.0 (the "License");
  + * you may not use this file except in compliance with the License.
  + * You may obtain a copy of the License at
  + *
  + *     http://www.apache.org/licenses/LICENSE-2.0
  + *
  + * Unless required by applicable law or agreed to in writing, software
  + * distributed under the License is distributed on an "AS IS" BASIS,
  + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  + * See the License for the specific language governing permissions and
  + * limitations under the License.
  + */
   package org.apache.jetspeed.security.spi.impl;
   
   import java.util.HashSet;
   import java.util.Set;
   
  +import org.apache.commons.lang.StringUtils;
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.apache.jetspeed.security.PasswordCredential;
   import org.apache.jetspeed.security.SecurityException;
   import org.apache.jetspeed.security.spi.CredentialHandler;
  +import org.apache.jetspeed.security.spi.impl.ldap.LdapUserCredentialDao;
  +import org.apache.jetspeed.security.spi.impl.ldap.LdapUserCredentialDaoImpl;
   
   /**
    * @see org.apache.jetspeed.security.spi.CredentialHandler
  - * @author <a href="mailto:dlestrat@apache.org">David Le Strat </a>
  + *
  + * @author <a href="mailto:mike.long@dataline.com">Mike Long</a>
    */
   public class LdapCredentialHandler implements CredentialHandler
   {
  +    /** The logger. */
  +    private static final Log LOG = LogFactory.getLog(LdapCredentialHandler.class);
  +
  +    /** The {@link LdapUserCredentialDao}. */
  +    private LdapUserCredentialDao ldap;
   
       /**
        * <p>
  -     * Default Constructor.
  +     * Default constructor.
        * </p>
        */
       public LdapCredentialHandler()
       {
  +        this(new LdapUserCredentialDaoImpl());
  +    }
  +
  +    public LdapCredentialHandler(LdapUserCredentialDao ldap)
  +    {
  +        this.ldap = ldap;
       }
  -    
  +
       /**
        * @see org.apache.jetspeed.security.spi.CredentialHandler#getPublicCredentials(java.lang.String)
        */
       public Set getPublicCredentials(String username)
       {
  -        Set publicCredentials = new HashSet();
  -        return publicCredentials;
  +        return new HashSet();
       }
   
       /**
        * @see org.apache.jetspeed.security.spi.CredentialHandler#getPrivateCredentials(java.lang.String)
        */
  -    public Set getPrivateCredentials(String username)
  +    public Set getPrivateCredentials(String uid)
       {
           Set privateCredentials = new HashSet();
  -        if (username.equals("ldap1"))
  +
  +        try
           {
  -            privateCredentials.add(new DefaultPasswordCredentialImpl(username, "password".toCharArray()));
  +            privateCredentials.add(new DefaultPasswordCredentialImpl(uid, ldap.getPassword(uid)));
           }
  -        else if (username.equals("ldap2"))
  +        catch (SecurityException e)
           {
  -            privateCredentials.add(new DefaultPasswordCredentialImpl(username, "password".toCharArray()));
  +            logSecurityException(e, uid);
           }
  -        else if (username.equals("ldap2"))
  +
  +        return privateCredentials;
  +    }
  +
  +    private void logSecurityException(SecurityException e, String uid)
  +    {
  +        if (LOG.isErrorEnabled())
           {
  -            privateCredentials.add(new DefaultPasswordCredentialImpl(username, "password".toCharArray()));
  +            LOG.error("Failure creating a PasswordCredential for InternalCredential uid:" + uid, e);
           }
  -        return privateCredentials;
       }
   
       /**
  -     * @see org.apache.jetspeed.security.spi.CredentialHandler#setPassword(java.lang.String,java.lang.String,java.lang.String)
  +     * <p>
  +     * Adds or updates a private password credential. <br>
  +     * If <code>oldPassword</code> is not null, the oldPassword will first be
  +     * checked (authenticated). <br>
  +     * </p>
  +     * 
  +     * @param uid The LDAP uid attribute.
  +     * @param oldPassword The old {@link PasswordCredential}.
  +     * @param newPassword The new {@link PasswordCredential}.
  +     * @throws SecurityException when the lookup fails because the user does not
  +     *             exist or the non-null password is not correct. Throws a
  +     *             {@link SecurityException}.
        */
  -    public void setPassword(String userName, String oldPassword, String newPassword ) throws SecurityException
  +    public void setPassword(String uid, String oldPassword, String newPassword) throws SecurityException
       {
  -        // TODO Auto-generated method stub
  +        validate(uid, newPassword);
  +
  +        if (!StringUtils.isEmpty(oldPassword))
  +        {
  +            ldap.authenticate(uid, oldPassword);
  +        }
  +
  +        ldap.changePassword(uid, newPassword);
       }
   
       /**
  -     * @see org.apache.jetspeed.security.spi.CredentialHandler#setPasswordEnabled(java.lang.String, boolean)
  +     * @see org.apache.jetspeed.security.spi.CredentialHandler#setPasswordEnabled(java.lang.String,
  +     *      boolean)
        */
       public void setPasswordEnabled(String userName, boolean enabled) throws SecurityException
       {
  -        // TODO Auto-generated method stub
  -
  +        // TODO Implement this.
       }
  -    
  +
       /**
  -     * @see org.apache.jetspeed.security.spi.CredentialHandler#setPasswordUpdateRequired(java.lang.String, boolean)
  +     * @see org.apache.jetspeed.security.spi.CredentialHandler#setPasswordUpdateRequired(java.lang.String,
  +     *      boolean)
        */
       public void setPasswordUpdateRequired(String userName, boolean updateRequired) throws SecurityException
       {
  -        // TODO Auto-generated method stub
  +        // TODO Implement this.
  +    }
  +
  +    /**
  +     * @see org.apache.jetspeed.security.spi.CredentialHandler#authenticate(java.lang.String, java.lang.String)
  +     */
  +    public boolean authenticate(String uid, String password) throws SecurityException
  +    {
  +        validate(uid, password);
   
  +        return ldap.authenticate(uid, password);
       }
  -    
  -    public boolean authenticate(String userName, String password)
  +
  +    /**
  +     * <p>
  +     * Validates the uid.
  +     * </p>
  +     * 
  +     * @param uid The uid.
  +     * @param password The password.
  +     * @throws SecurityException Throws a {@link SecurityException}.
  +     */
  +    private void validate(String uid, String password) throws SecurityException
       {
  -        if (userName.equals("ldap1") || userName.equals("ldap2") || userName.equals("ldap3"))
  +        if (StringUtils.isEmpty(password))
  +        {
  +            throw new SecurityException("The password cannot be null or empty.");
  +        }
  +
  +        if (StringUtils.isEmpty(uid))
           {
  -            return "password".equals(password);
  +            throw new SecurityException("The uid cannot be null or empty.");
           }
  -        return false;
       }
  -}
  +}
  \ No newline at end of file
  
  
  
  1.3       +116 -29   jakarta-jetspeed-2/components/security/src/java/org/apache/jetspeed/security/spi/impl/LdapUserSecurityHandler.java
  
  Index: LdapUserSecurityHandler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-jetspeed-2/components/security/src/java/org/apache/jetspeed/security/spi/impl/LdapUserSecurityHandler.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- LdapUserSecurityHandler.java	27 Oct 2004 22:09:28 -0000	1.2
  +++ LdapUserSecurityHandler.java	21 Feb 2005 21:34:47 -0000	1.3
  @@ -15,69 +15,130 @@
   package org.apache.jetspeed.security.spi.impl;
   
   import java.security.Principal;
  -import java.util.LinkedList;
  +import java.util.ArrayList;
  +import java.util.Arrays;
   import java.util.List;
   
  +import org.apache.commons.lang.StringUtils;
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
   import org.apache.jetspeed.security.SecurityException;
   import org.apache.jetspeed.security.UserPrincipal;
   import org.apache.jetspeed.security.impl.UserPrincipalImpl;
   import org.apache.jetspeed.security.spi.UserSecurityHandler;
  +import org.apache.jetspeed.security.spi.impl.ldap.LdapUserSecurityDao;
  +import org.apache.jetspeed.security.spi.impl.ldap.LdapUserSecurityDaoImpl;
   
   /**
    * @see org.apache.jetspeed.security.spi.UserSecurityHandler
  - * @author <a href="mailto:dlestrat@apache.org">David Le Strat</a>
  + * @author <a href="mailto:mike.long@dataline.com">Mike Long </a>
    */
   public class LdapUserSecurityHandler implements UserSecurityHandler
   {
  +    /** The logger. */
  +    private static final Log LOG = LogFactory.getLog(LdapUserSecurityHandler.class);
  +
  +    /** The {@link LdapUserSecurityDao}. */
  +    private LdapUserSecurityDao ldap;
  +
  +    /**
  +     * @param ldap The {@link LdapUserSecurityDao}.
  +     */
  +    public LdapUserSecurityHandler(LdapUserSecurityDao ldap)
  +    {
  +        this.ldap = ldap;
  +    }
  +
       /**
        * <p>
  -     * Default Constructor.
  +     * Default constructor.
        * </p>
        */
       public LdapUserSecurityHandler()
       {
  +        this(new LdapUserSecurityDaoImpl());
       }
  -    
  +
       /**
  +     * <p>
  +     * Lookup the user by his UID attribute on the Ldap Server.
  +     * </p>
  +     * 
  +     * @return true if the Ldap Server finds a user with that UID; false if he
  +     *         is not found or some sort of NamingException occurred.
        * @see org.apache.jetspeed.security.spi.UserSecurityHandler#isUserPrincipal(java.lang.String)
        */
  -    public boolean isUserPrincipal(String userName)
  +    public boolean isUserPrincipal(String uid)
       {
  -        return userName.equals("ldap1") || userName.equals("ldap2") || userName.equals("ldap3");
  +        verifyUid(uid);
  +        return getUserPrincipal(uid) != null;
       }
  -    
  +
       /**
        * @see org.apache.jetspeed.security.spi.UserSecurityHandler#getUserPrincipal(java.lang.String)
        */
  -    public Principal getUserPrincipal(String username)
  +    public Principal getUserPrincipal(String uid)
       {
  -        UserPrincipal userPrincipal = null;
  -        if (username.equals("ldap1"))
  +        verifyUid(uid);
  +        try
           {
  -            userPrincipal = new UserPrincipalImpl(UserPrincipalImpl.getPrincipalNameFromFullPath("/user/ldap1"));
  +            String dn = ldap.lookupByUid(uid);
  +
  +            if (!StringUtils.isEmpty(dn))
  +            {
  +                return new UserPrincipalImpl(uid);
  +            }
           }
  -        else if (username.equals("ldap2"))
  +        catch (SecurityException e)
           {
  -            userPrincipal = new UserPrincipalImpl(UserPrincipalImpl.getPrincipalNameFromFullPath("/user/ldap2"));
  +            logSecurityException(e, uid);
           }
  -        else if (username.equals("ldap3"))
  +
  +        return null;
  +    }
  +
  +    /**
  +     * <p>
  +     * Verify the uid.
  +     * </p>
  +     * 
  +     * @param uid The uid.
  +     */
  +    private void verifyUid(String uid)
  +    {
  +        if (StringUtils.isEmpty(uid))
           {
  -            userPrincipal = new UserPrincipalImpl(UserPrincipalImpl.getPrincipalNameFromFullPath("/user/ldap3"));
  +            throw new IllegalArgumentException("The uid cannot be null or empty.");
           }
  -        return userPrincipal;
       }
  -    
  +
  +    /**
  +     * @param se SecurityException Throws a {@link SecurityException}.
  +     * @param uid The uid.
  +     */
  +    private void logSecurityException(SecurityException se, String uid)
  +    {
  +        if (LOG.isErrorEnabled())
  +        {
  +            LOG.error("An LDAP error has occurred for user uid:" + uid, se);
  +        }
  +    }
  +
       /**
        * @see org.apache.jetspeed.security.spi.UserSecurityHandler#getUserPrincipals(java.lang.String)
        */
       public List getUserPrincipals(String filter)
       {
  -        List userPrincipals = new LinkedList();
  -        userPrincipals.add(new UserPrincipalImpl(UserPrincipalImpl.getPrincipalNameFromFullPath("/user/ldap1")));
  -        userPrincipals.add(new UserPrincipalImpl(UserPrincipalImpl.getPrincipalNameFromFullPath("/user/ldap2")));
  -        userPrincipals.add(new UserPrincipalImpl(UserPrincipalImpl.getPrincipalNameFromFullPath("/user/ldap3")));
  +        try
  +        {
  +            return Arrays.asList(ldap.find(filter));
  +        }
  +        catch (SecurityException e)
  +        {
  +            logSecurityException(e, filter);
  +        }
   
  -        return userPrincipals;
  +        return new ArrayList();
       }
   
       /**
  @@ -85,23 +146,49 @@
        */
       public void addUserPrincipal(UserPrincipal userPrincipal) throws SecurityException
       {
  -        // To implement.
  +        verifyUserPrincipal(userPrincipal);
  +
  +        String uid = userPrincipal.getName();
  +        if (isUserPrincipal(uid))
  +        {
  +            throw new SecurityException("The user:" + uid + " already exists.");
  +        }
  +        ldap.create(uid);
       }
  -    
  +
       /**
        * @see org.apache.jetspeed.security.spi.UserSecurityHandler#updateUserPrincipal(org.apache.jetspeed.security.UserPrincipal)
        */
       public void updateUserPrincipal(UserPrincipal userPrincipal) throws SecurityException
       {
  -        // To implement.
  +        verifyUserPrincipal(userPrincipal);
  +        String uid = userPrincipal.getName();
  +        if (!isUserPrincipal(uid))
  +        {
  +            ldap.create(uid);
  +        }
  +    }
  +
  +    /**
  +     * @param userPrincipal
  +     */
  +    private void verifyUserPrincipal(UserPrincipal userPrincipal)
  +    {
  +        if (userPrincipal == null)
  +        {
  +            throw new IllegalArgumentException("The UserPrincipal cannot be null or empty.");
  +        }
       }
  -    
  +
       /**
        * @see org.apache.jetspeed.security.spi.UserSecurityHandler#removeUserPrincipal(org.apache.jetspeed.security.UserPrincipal)
        */
       public void removeUserPrincipal(UserPrincipal userPrincipal) throws SecurityException
       {
  -        // To implement        
  -    }
  +        verifyUserPrincipal(userPrincipal);
  +
  +        String uid = userPrincipal.getName();
   
  -}
  +        ldap.delete(uid);
  +    }
  +}
  \ No newline at end of file
  
  
  
  1.4       +79 -68    jakarta-jetspeed-2/components/security/src/test/org/apache/jetspeed/security/TestAuthenticationProviderProxy.java
  
  Index: TestAuthenticationProviderProxy.java
  ===================================================================
  RCS file: /home/cvs/jakarta-jetspeed-2/components/security/src/test/org/apache/jetspeed/security/TestAuthenticationProviderProxy.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- TestAuthenticationProviderProxy.java	8 Nov 2004 03:23:36 -0000	1.3
  +++ TestAuthenticationProviderProxy.java	21 Feb 2005 21:34:47 -0000	1.4
  @@ -15,11 +15,9 @@
   package org.apache.jetspeed.security;
   
   import java.util.ArrayList;
  -import java.util.Collection;
   import java.util.Iterator;
   import java.util.List;
   
  -
   import junit.framework.Test;
   import junit.framework.TestSuite;
   
  @@ -30,16 +28,17 @@
   import org.apache.jetspeed.security.impl.RoleManagerImpl;
   import org.apache.jetspeed.security.impl.SecurityProviderImpl;
   import org.apache.jetspeed.security.impl.UserManagerImpl;
  -import org.apache.jetspeed.security.spi.CredentialHandler;
  -import org.apache.jetspeed.security.spi.UserSecurityHandler;
  -import org.apache.jetspeed.security.spi.impl.LdapCredentialHandler;
  -import org.apache.jetspeed.security.spi.impl.LdapUserSecurityHandler;
   import org.apache.jetspeed.security.util.test.AbstractSecurityTestcase;
   
   /**
  - * <p>Unit testing for {@link TestAuthenticationProviderProxy}.</p>
  - *
  - * @author <a href="mailto:dlestrat@apache.org">David Le Strat</a>
  + * <p>
  + * Unit testing for {@link TestAuthenticationProviderProxy}.
  + * </p>
  + * 
  + * TODO Needs an LDAP server configured for most of those tests to be valid. 
  + *      Commented until embedded ldap is supported.
  + * 
  + * @author <a href="mailto:dlestrat@apache.org">David Le Strat </a>
    */
   public class TestAuthenticationProviderProxy extends AbstractSecurityTestcase
   {
  @@ -51,48 +50,50 @@
       {
           super.setUp();
           destroyTestData();
  -        
  +
           // The LDAP user security handler.
  -        UserSecurityHandler ldapUsh = new LdapUserSecurityHandler();
  +        // is supported.
  +        // UserSecurityHandler ldapUsh = new LdapUserSecurityHandler();
           // The LDAP credential handler.
  -        CredentialHandler ldapCh = new LdapCredentialHandler();
  -        
  +        // CredentialHandler ldapCh = new LdapCredentialHandler();
  +
           // Security Providers.
  -        AuthenticationProvider defaultAtnProvider = new AuthenticationProviderImpl("DefaultAuthenticator", "The default authenticator", "login.conf", ch, ush);
  -        AuthenticationProvider ldapAtnProvider = new AuthenticationProviderImpl("LdapAuthenticator", "The ldap authenticator", ldapCh, ldapUsh);
  +        AuthenticationProvider defaultAtnProvider = new AuthenticationProviderImpl("DefaultAuthenticator",
  +                "The default authenticator", "login.conf", ch, ush);
  +        // AuthenticationProvider ldapAtnProvider = new
  +        // AuthenticationProviderImpl("LdapAuthenticator", "The ldap
  +        // authenticator", ldapCh, ldapUsh);
   
           List atnProviders = new ArrayList();
           atnProviders.add(defaultAtnProvider);
  -        atnProviders.add(ldapAtnProvider);
  -        AuthenticationProviderProxy atnProviderProxy = new AuthenticationProviderProxyImpl(atnProviders, "DefaultAuthenticator");
  -        
  +        // atnProviders.add(ldapAtnProvider);
  +        AuthenticationProviderProxy atnProviderProxy = new AuthenticationProviderProxyImpl(atnProviders,
  +                "DefaultAuthenticator");
  +
           // Need to override the AbstractSecurityTestcase behavior.
           securityProvider = new SecurityProviderImpl(atnProviderProxy, rsh, gsh, smh);
           ums = new UserManagerImpl(securityProvider);
           gms = new GroupManagerImpl(securityProvider);
           rms = new RoleManagerImpl(securityProvider);
  -        
  +
           // Login module.
           new LoginModuleProxyImpl(ums);
       }
  -   
  +
       /**
        * @see junit.framework.TestCase#tearDown()
        */
       public void tearDown() throws Exception
  -    {       
  +    {
           destroyTestData();
           super.tearDown();
       }
   
  -  
  -    
       public static Test suite()
       {
  -           return new TestSuite(TestAuthenticationProviderProxy.class);
  +        return new TestSuite(TestAuthenticationProviderProxy.class);
       }
   
  -
       /**
        * <p>
        * Test user manager.
  @@ -101,55 +102,62 @@
       public void testUserManager()
       {
           initTestData();
  -        
  +
           try
           {
               // Get user.
               // From LDAP.
  -            User user = ums.getUser("ldap1");
  -            assertNotNull(user);
  -            assertEquals("ldap1", SecurityHelper.getPrincipal(user.getSubject(), UserPrincipal.class).getName());
  +            // ldap is supported.
  +            // User user = ums.getUser("ldap1");
  +            // assertNotNull(user);
  +            // assertEquals("ldap1",
  +            // SecurityHelper.getPrincipal(user.getSubject(),
  +            // UserPrincipal.class).getName());
  +
               // From RDBMS.
  -            user = ums.getUser("anonuser1");
  +            User user = ums.getUser("anonuser1");
               assertNotNull(user);
  -            assertEquals("anonuser1", SecurityHelper.getPrincipal(user.getSubject(), UserPrincipal.class).getName());   
  -            
  +            assertEquals("anonuser1", SecurityHelper.getPrincipal(user.getSubject(), UserPrincipal.class).getName());
  +
               // Authenticate.
               // From Ldap.
  -            assertTrue(ums.authenticate("ldap2", "password"));
  -            assertFalse(ums.authenticate("ldap3", "pword"));
  +            // assertTrue(ums.authenticate("ldap2", "password"));
  +            // assertFalse(ums.authenticate("ldap3", "pword"));
  +
               // From RDBMS.
               assertTrue(ums.authenticate("anonuser2", "password"));
               assertFalse(ums.authenticate("anonuser3", "pword"));
  -            
  +
               // Get all users. 5 rdbms users + 3 ldap users.
               Iterator users = ums.getUsers("");
               int count = 0;
               while (users.hasNext())
               {
                   users.next();
  -                count ++;
  +                count++;
               }
  -            assertEquals(8, count);
  +            // assertEquals(8, count);
  +
  +            assertEquals(5, count);
           }
           catch (SecurityException sex)
           {
               assertTrue("security exception caught: " + sex, false);
           }
   
  -        
           destroyTestData();
       }
  -    
  +
       /**
        * <p>
        * Test role manager.
        * </p>
        */
  +    /*
       public void testRoleManager()
       {
           initTestData();
  -        
  +
           try
           {
               // Add user to role.
  @@ -160,21 +168,21 @@
               assertNotNull(roles);
               // Given the hierarchy resolution. Should contain 2 roles.
               assertEquals("should contain 2 roles", 2, roles.size());
  -            
  +
               // Is user in roles?
               assertTrue(rms.isUserInRole("ldap1", "testrole1"));
               assertTrue(rms.isUserInRole("ldap1", "testrole1.subrole1"));
  -            
  +
               // Remove role mapping.
               rms.removeRoleFromUser("ldap1", "testrole1.subrole1");
               // Get role mapping.
               roles = rms.getRolesForUser("ldap1");
               assertNotNull(roles);
               assertEquals("should not contain any role", 0, roles.size());
  -            
  +
               // The mapping entry should be gone.
               assertNull(securityAccess.getInternalUserPrincipal("ldap1", true));
  -            
  +
               // Is user in roles?
               assertFalse(rms.isUserInRole("ldap1", "testrole1"));
               assertFalse(rms.isUserInRole("ldap1", "testrole1.subrole1"));
  @@ -183,19 +191,21 @@
           {
               assertTrue("security exception caught: " + sex, false);
           }
  -        
  +
           destroyTestData();
       }
  -    
  +    */
  +
       /**
        * <p>
        * Test group manager.
        * </p>
        */
  +    /*
       public void testGroupManager()
       {
           initTestData();
  -        
  +
           try
           {
               // Add user to group.
  @@ -206,21 +216,21 @@
               assertNotNull(groups);
               // Given the hierarchy resolution. Should contain 2 groups.
               assertEquals("should contain 2 groups", 2, groups.size());
  -            
  +
               // Is user in groups?
               assertTrue(gms.isUserInGroup("ldap1", "testgroup1"));
               assertTrue(gms.isUserInGroup("ldap1", "testgroup1.subgroup1"));
  -            
  +
               // Remove group mapping.
               gms.removeUserFromGroup("ldap1", "testgroup1.subgroup1");
               // Get group mapping.
               groups = gms.getGroupsForUser("ldap1");
               assertNotNull(groups);
               assertEquals("should not contain any group", 0, groups.size());
  -            
  +
               // The mapping entry should be gone.
               assertNull(securityAccess.getInternalUserPrincipal("ldap1", true));
  -            
  +
               // Is user in groups?
               assertFalse(gms.isUserInGroup("ldap1", "testgroup1"));
               assertFalse(gms.isUserInGroup("ldap1", "testgroup1.subgroup1"));
  @@ -229,10 +239,11 @@
           {
               assertTrue("security exception caught: " + sex, false);
           }
  -        
  +
           destroyTestData();
       }
  -    
  +    */
  +
       /**
        * <p>
        * Init test data.
  @@ -241,11 +252,11 @@
       private void initTestData()
       {
           final String[] users = new String[] { "anonuser1", "anonuser2", "anonuser3", "anonuser4", "anonuser5", };
  -        final String[] roles = new String[] { "testrole1", "testrole1.subrole1", "testrole1.subrole1.subrole2", "testrole2",
  -                "testrole2.subrole1" };
  -        final String[] groups = new String[] { "testgroup1", "testgroup1.subgroup1", "testgroup1.subgroup1.subgroup2", "testgroup2",
  -        "testgroup2.subgroup1" };
  -        
  +        final String[] roles = new String[] { "testrole1", "testrole1.subrole1", "testrole1.subrole1.subrole2",
  +                "testrole2", "testrole2.subrole1" };
  +        final String[] groups = new String[] { "testgroup1", "testgroup1.subgroup1", "testgroup1.subgroup1.subgroup2",
  +                "testgroup2", "testgroup2.subgroup1" };
  +
           for (int i = 0; i < users.length; i++)
           {
               try
  @@ -257,7 +268,7 @@
                   System.err.println(e.toString());
               }
           }
  -        
  +
           for (int i = 0; i < roles.length; i++)
           {
               try
  @@ -269,7 +280,7 @@
                   System.err.println(e.toString());
               }
           }
  -        
  +
           for (int i = 0; i < groups.length; i++)
           {
               try
  @@ -297,8 +308,8 @@
               String userName;
               while (userIter.hasNext())
               {
  -                user = (User)userIter.next();
  -                userName = SecurityHelper.getPrincipal(user.getSubject(),UserPrincipal.class).getName();
  +                user = (User) userIter.next();
  +                userName = SecurityHelper.getPrincipal(user.getSubject(), UserPrincipal.class).getName();
                   ums.removeUser(userName);
               }
           }
  @@ -307,10 +318,10 @@
               System.err.println(e.toString());
           }
   
  -        final String[] roles = new String[] { "testrole1", "testrole1.subrole1", "testrole1.subrole1.subrole2", "testrole2",
  -        "testrole2.subrole1" };
  -        final String[] groups = new String[] { "testgroup1", "testgroup1.subgroup1", "testgroup1.subgroup1.subgroup2", "testgroup2",
  -        "testgroup2.subgroup1" };
  +        final String[] roles = new String[] { "testrole1", "testrole1.subrole1", "testrole1.subrole1.subrole2",
  +                "testrole2", "testrole2.subrole1" };
  +        final String[] groups = new String[] { "testgroup1", "testgroup1.subgroup1", "testgroup1.subgroup1.subgroup2",
  +                "testgroup2", "testgroup2.subgroup1" };
   
           for (int i = 0; i < roles.length; i++)
           {
  @@ -323,7 +334,7 @@
                   System.err.println(e.toString());
               }
           }
  -        
  +
           for (int i = 0; i < groups.length; i++)
           {
               try
  @@ -336,4 +347,4 @@
               }
           }
       }
  -}
  +}
  \ No newline at end of file
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jetspeed-dev-help@jakarta.apache.org