// Copyright 2013 Google Inc. All Rights Reserved.
//
// 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 com.google.enterprise.adaptor.ad;

import com.google.common.annotations.VisibleForTesting;
import com.google.enterprise.adaptor.AbstractAdaptor;
import com.google.enterprise.adaptor.AdaptorContext;
import com.google.enterprise.adaptor.Config;
import com.google.enterprise.adaptor.DocIdPusher;
import com.google.enterprise.adaptor.GroupPrincipal;
import com.google.enterprise.adaptor.PollingIncrementalLister;
import com.google.enterprise.adaptor.Principal;
import com.google.enterprise.adaptor.Request;
import com.google.enterprise.adaptor.Response;
import com.google.enterprise.adaptor.UserPrincipal;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.naming.InterruptedNamingException;
import javax.naming.NamingException;

/** Adaptor for Active Directory. */
public class AdAdaptor extends AbstractAdaptor
    implements PollingIncrementalLister {
  private static final Logger log
      = Logger.getLogger(AdAdaptor.class.getName());
  private static final boolean CASE_SENSITIVITY = false;
  /**
   * Only one crawl (full or incremental) is done at a time, however:
   * when a full crawl is invoked, we wait until the lock is available;
   * when an incremental crawl is invoked, we immediately return if the lock
   * isn't available.
   */
  private final ReentrantLock mutex = new ReentrantLock();

  private String namespace;
  private String defaultUser;  // used if an AD doesn't override
  private String defaultPassword;  // likewise
  private List<AdServer> servers = new ArrayList<AdServer>();
  private Map<String, String> localizedStrings;
  private boolean feedBuiltinGroups;
  private GroupCatalog lastCompleteGroupCatalog = null;
  private String ldapTimeoutInMillis;

  @Override
  public void initConfig(Config config) {
    config.addKey("ad.servers", null);
    config.addKey("adaptor.namespace", "Default");
    config.addKey("ad.defaultUser", "");
    config.addKey("ad.defaultPassword", "");
    config.addKey("ad.localized.Everyone", "Everyone");
    config.addKey("ad.localized.NTAuthority", "NT Authority");
    config.addKey("ad.localized.Interactive", "Interactive");
    config.addKey("ad.localized.AuthenticatedUsers", "Authenticated Users");
    config.addKey("ad.localized.Builtin", "BUILTIN");
    config.addKey("ad.feedBuiltinGroups", "false");
    config.addKey("ad.ldapReadTimeoutSecs", "90");
  }

  @Override
  public void init(AdaptorContext context) throws Exception {
    Config config = context.getConfig();
    namespace = config.getValue("adaptor.namespace");
    log.config("common namespace: " + namespace);
    defaultUser = config.getValue("ad.defaultUser");
    defaultPassword = context.getSensitiveValueDecoder().decodeValue(
        config.getValue("ad.defaultPassword"));
    feedBuiltinGroups = Boolean.parseBoolean(
        config.getValue("ad.feedBuiltinGroups"));
    ldapTimeoutInMillis = parseLdapTimeoutInMillis(
        config.getValue("ad.ldapReadTimeoutSecs"));
    // register for incremental pushes
    context.setPollingIncrementalLister(this);
    List<Map<String, String>> serverConfigs
        = config.getListOfConfigs("ad.servers");
    servers.clear();  // in case init gets called again
    for (Map<String, String> singleServerConfig : serverConfigs) {
      String host = singleServerConfig.get("host");
      int port = 389;
      if (singleServerConfig.containsKey("port")) {
        port = Integer.parseInt(singleServerConfig.get("port"));
      }
      Method method = Method.STANDARD;
      if (singleServerConfig.containsKey("method")) {
        String methodStr = singleServerConfig.get("method").toLowerCase();
        if ("ssl".equals(methodStr)) {
          method = Method.SSL;
        } else if (!"standard".equals(methodStr)) {
          throw new IllegalArgumentException("invalid method: " + methodStr);
        }
      }
      String principal = singleServerConfig.get("user");
      if (null == principal) {
        principal = defaultUser;
      }
      if (principal.isEmpty()) {
        throw new IllegalStateException("user not specified for host " + host);
      }
      String passwd = context.getSensitiveValueDecoder().decodeValue(
          singleServerConfig.get("password"));
      if (null == passwd) {
        passwd = defaultPassword;
      }
      if (passwd.isEmpty()) {
        throw new IllegalStateException("password not specified for host "
            + host);
      }
      AdServer adServer = newAdServer(method, host, port, principal, passwd,
          ldapTimeoutInMillis);
      adServer.initialize();
      servers.add(adServer);
      Map<String, String> dup = new TreeMap<String, String>(singleServerConfig);
      dup.put("password", "XXXXXX");  // hide password
      log.log(Level.CONFIG, "AD server spec: {0}", dup);
    }
    localizedStrings = config.getValuesWithPrefix("ad.localized.");
  }

  /**
   * This method exists specifically to be overwritten in the test class, in
   * order to inject a version of AdServer that uses mocks.
   */
  @VisibleForTesting
  AdServer newAdServer(Method method, String host, int port,
      String principal, String passwd, String ldapTimeoutInMillis) {
    return new AdServer(method, host, port, principal, passwd,
        ldapTimeoutInMillis);
  }

  private static String parseLdapTimeoutInMillis(String timeInSeconds) {
    if (timeInSeconds.equals("0") || timeInSeconds.trim().equals("")) {
      timeInSeconds = "90";
      log.log(Level.CONFIG, "ad.ldapReadTimeoutSecs set to default of 90 sec.");
    }
    try {
      return String.valueOf(1000L * Integer.parseInt(timeInSeconds));
    } catch (NumberFormatException e) {
      throw new IllegalArgumentException("invalid ad.ldapReadTimeoutSecs: " +
          timeInSeconds);
    }
  }

  /** This adaptor does not serve documents. */
  @Override
  public void getDocContent(Request req, Response resp) throws IOException {
    resp.respondNotFound();
  }

  /** Call default main for adaptors. */
  public static void main(String[] args) {
    AbstractAdaptor.main(new AdAdaptor(), args);
  }

  /** Crawls/pushes all groups from all AdServers. */

  @Override
  public void getDocIds(DocIdPusher pusher) throws InterruptedException,
      IOException {
    log.log(Level.FINER, "getDocIds invoked - waiting for lock.");
    mutex.lock();
    try {
      clearLastCompleteGroupCatalog();
      GroupCatalog cumulativeCatalog = makeFullCatalog();
      // all servers were able to successfully populate the catalog: do a push
      cumulativeCatalog.resolveForeignSecurityPrincipals();
      Map<GroupPrincipal, List<Principal>> groups =
          cumulativeCatalog.makeDefs();
      pusher.pushGroupDefinitions(groups, CASE_SENSITIVITY);
      // TODO(myk): clear membership information from cache - retain only the
      // entities in bySid, byDn, and wellKnownMembership.
      lastCompleteGroupCatalog = cumulativeCatalog;
    } finally {
      mutex.unlock();
      log.log(Level.FINE, "getDocIds ending - lock released.");
    }
  }

  private GroupCatalog makeFullCatalog() throws InterruptedException,
      IOException {
    GroupCatalog cumulativeCatalog = new GroupCatalog(localizedStrings,
        namespace, feedBuiltinGroups);
    for (AdServer server : servers) {
      try {
        server.ensureConnectionIsCurrent();
        GroupCatalog catalog = new GroupCatalog(localizedStrings, namespace,
              feedBuiltinGroups);
        catalog.readEverythingFrom(server);
        cumulativeCatalog.add(catalog);
      } catch (NamingException ne) {
        String host = server.getHostName();
        throw new IOException("could not get entities from " + host, ne);
      }
    }
    return cumulativeCatalog;
  }

  /**
   * Attempts an incremental push of updated groups from all AdServers.
   * <p>
   * When a server cannot do an incremental push, it does a full crawl without
   * doing a push afterwards -- this sets up its state so that subsequent
   * incremental pushes can work.  A future version of this method will do the
   * full crawl ignoring the "member" attribute.
   */
  @Override
  public void getModifiedDocIds(DocIdPusher pusher) throws InterruptedException,
      IOException {
    if (!mutex.tryLock()) {
      log.log(Level.FINE, "getModifiedDocIds could not acquire lock; " +
          "will retry later.");
      return;
    }
    try {
      log.log(Level.FINE, "getModifiedDocIds starting - acquired lock.");

      for (AdServer server : servers) {
        String previousServiceName = server.getDsServiceName();
        String previousInvocationId = server.getInvocationID();
        long previousHighestUSN = server.getHighestCommittedUSN();
        try {
          server.ensureConnectionIsCurrent();
          // TODO(myk): combine each server's resulting Entities into one Set
          lastCompleteGroupCatalog.readUpdatesFrom(server, previousServiceName,
              previousInvocationId, previousHighestUSN);
        } catch (NamingException ne) {
          // invalidate the saved group catalog
          clearLastCompleteGroupCatalog();
          String host = server.getHostName();
          throw new IOException("could not get entities from " + host, ne);
        }
      }

      // all servers were able to successfully update the catalog: do a push
      lastCompleteGroupCatalog.resolveForeignSecurityPrincipals();
      Map<GroupPrincipal, List<Principal>> groups =
          lastCompleteGroupCatalog.makeDefs();
      // TODO(myk): pass on (only) new/modified entities to resolve/makeDefs,
      // so that we're only pushing the new/modified groups below.
      pusher.pushGroupDefinitions(groups, CASE_SENSITIVITY);
      // TODO(myk): clear membership information from cache - retain only the
      // entities in bySid, byDn, and wellKnownMembership.
    } finally {
      mutex.unlock();
      log.log(Level.FINE, "getModifiedDocIds ending - lock released.");
    }
  }

  // don't expose the <code>lastCompleteGroupCatalog</code> field, but do allow
  // tests to clear it
  @VisibleForTesting
  void clearLastCompleteGroupCatalog() {
    lastCompleteGroupCatalog = null;
  }

  // Space for all group info, organized in different ways
  @VisibleForTesting
  static class GroupCatalog {
    Map<String, String> localizedStrings;
    String namespace;
    boolean feedBuiltinGroups;
    Set<AdEntity> entities = new HashSet<AdEntity>();
    Map<AdEntity, Set<String>> members = new HashMap<AdEntity, Set<String>>();

    Map<String, AdEntity> bySid = new HashMap<String, AdEntity>();
    Map<String, AdEntity> byDn = new HashMap<String, AdEntity>();
    Map<AdEntity, String> domain = new HashMap<AdEntity, String>();

    final AdEntity everyone;
    final AdEntity interactive;
    final AdEntity authenticatedUsers;
    final Map<AdEntity, Set<String>> wellKnownMembership;

    public GroupCatalog(Map<String, String> localizedStrings, String namespace,
        boolean feedBuiltinGroups) {
      this.localizedStrings = localizedStrings;
      this.namespace = namespace;
      this.feedBuiltinGroups = feedBuiltinGroups;
      everyone = new AdEntity("S-1-1-0",
          MessageFormat.format("CN={0}",
          localizedStrings.get("Everyone")));
      interactive = new AdEntity("S-1-5-4",
          MessageFormat.format("CN={0},DC={1}",
          localizedStrings.get("Interactive"),
          localizedStrings.get("NTAuthority")));
      authenticatedUsers = new AdEntity("S-1-5-11" ,
          MessageFormat.format("CN={0},DC={1}",
          localizedStrings.get("AuthenticatedUsers"),
          localizedStrings.get("NTAuthority")));
      wellKnownMembership = new HashMap<AdEntity, Set<String>>();
      wellKnownMembership.put(everyone, new TreeSet<String>());
      wellKnownMembership.put(interactive, new TreeSet<String>());
      wellKnownMembership.put(authenticatedUsers, new TreeSet<String>());

      // To save space on GSA onboard groups database, we add "everyone" as a
      // member to "Interactive" and "authenticated users" groups.
      // Each user from domain will be added as member of "everyone" group
      // and user will be indirect member for
      // "Interactive" and "authenticated users" groups.
      wellKnownMembership.get(interactive).add(everyone.getDn());
      wellKnownMembership.get(authenticatedUsers).add(everyone.getDn());

      entities.add(everyone);
      entities.add(interactive);
      entities.add(authenticatedUsers);

      bySid.put(everyone.getSid(), everyone);
      byDn.put(everyone.getDn(), everyone);

      bySid.put(interactive.getSid(), interactive);
      byDn.put(interactive.getDn(), interactive);
      domain.put(interactive, localizedStrings.get("NTAuthority"));

      bySid.put(authenticatedUsers.getSid(), authenticatedUsers);
      byDn.put(authenticatedUsers.getDn(), authenticatedUsers);
      domain.put(authenticatedUsers, localizedStrings.get("NTAuthority"));
    }

    @VisibleForTesting
    GroupCatalog(Map<String, String> localizedStrings, String namespace,
        boolean feedBuiltinGroups, Set<AdEntity> entities,
        Map<AdEntity, Set<String>> members,
        Map<String, AdEntity> bySid,
        Map<String, AdEntity> byDn,
        Map<AdEntity, String> domain) {
      this(localizedStrings, namespace, feedBuiltinGroups);
      this.entities.clear();
      this.entities.addAll(entities);
      this.members.putAll(members);
      this.bySid.putAll(bySid);
      this.byDn.putAll(byDn);
      this.domain.putAll(domain);
    }

    @VisibleForTesting
    void readEverythingFrom(AdServer server) throws InterruptedNamingException {
      // TODO(myk): Phase II: indicate whether or not this search should
      // include members
      log.log(Level.FINE, "Starting full crawl.");
      // LDAP_MATCHING_RULE_BIT_AND = 1.2.840.113556.1.4.803
      // and ADS_GROUP_TYPE_SECURITY_ENABLED = 2147483648.
      entities = server.search("(|(&(objectClass=group)"
          + "(groupType:1.2.840.113556.1.4.803:=2147483648))"
          + "(&(objectClass=user)(objectCategory=person)))",
          /*deleted=*/ false,
          new String[] { "uSNChanged", "sAMAccountName", "objectGUID;binary",
              "objectSid;binary", "userPrincipalName", "primaryGroupId",
              "member", "userAccountControl" });
      // disabled groups handled later, in makeDefs()
      log.log(Level.FINE, "Ending full crawl - now starting processing.");
      processEntities(entities, server.getnETBIOSName());
    }

    /**
     * Do an AD search for only groups/users that have been updated since the
     * previous full or incremental search.
     * <p>If either <code>getDsServiceName()</code> or
     * <code>server.getInvocationID()</code> have changed, the cache is stale
     * and (only) a full crawl is done, to refresh the cache.  If neither have
     * changed, then only groups/users that have a <code>uSNChanged</code>
     * attribute newer than the <code>previousHighestUSN</code> parameter are
     * retrieved and returned.
     * @param server the Active Directory server to query
     * @param previousServiceName last-crawled value of
     *     <code>getDsServiceName()</code>
     * @param previousInvocationId last-crawled value of
     *     <code>server.getInvocationID()</code>
     * @param previousHighestUSN last-crawled value of
     *     <code>server.getHighestCommittedUSN()</code>
     * <code>previousHighestUSN</code>.
     */
     /* TODO(myk): add
     * @return all instances of <code>AdEntity</code> that are users/groups that
     *     have a <code>uSNChanged</code> attribute newer than, or
     *     <code>Collections.emptySet()</code> when the cache had been stale.
     */
    @VisibleForTesting
    void readUpdatesFrom(AdServer server, String previousServiceName,
        String previousInvocationId, long previousHighestUSN)
        throws InterruptedNamingException {
      // TODO(myk): Determine whether adaptors should include code to get/set
      // last full sync time, and if exceeding some threshhold should force a
      // full crawl.
      String currentServiceName = server.getDsServiceName();
      String currentInvocationId = server.getInvocationID();
      long currentHighestUSN = server.getHighestCommittedUSN();
      if (!currentServiceName.equals(previousServiceName)) {
        // only log a warning if previous service name was set to something
        if (previousServiceName != null) {
          log.log(Level.WARNING, "Directory Controller changed from {0} to {1} "
              + "-- performing full recrawl.  Consider configuring AD server to"
              + " connect directly to FQDN address of domain controller for "
              + "partial updates support.",
              new Object[]{previousServiceName, currentServiceName});
        }
        readEverythingFrom(server);
        return;
        //TODO(myk): return Collections.emptySet();
      }
      if (!currentInvocationId.equals(previousInvocationId)) {
        log.log(Level.WARNING,
            "Directory Controller {0} has been restored from backup.  "
            + "Performing full recrawl.", currentServiceName);
        readEverythingFrom(server);
        return;
        //TODO(myk): return Collections.emptySet();
      }
      if (currentHighestUSN == previousHighestUSN) {
        log.log(Level.INFO, "No updates on server {0} -- no crawl invoked.",
            server);
        return;
        //TODO(myk): return Collections.emptySet();
      }
      log.log(Level.INFO, "Attempting incremental crawl.");
      incrementalCrawl(server, previousHighestUSN, currentHighestUSN);
    }

    private void processEntities(Set<AdEntity> entities, String nETBIOSName) {
      log.log(Level.FINE, "received {0} entities from server", entities.size());
      for (AdEntity e : entities) {
        bySid.put(e.getSid(), e);
        byDn.put(e.getDn(), e);
        // TODO(pjo): Have AdServer put domain into AdEntity during search
        domain.put(e, e.getSid().startsWith("S-1-5-32-") ?
            localizedStrings.get("Builtin") : nETBIOSName);
      }
      initializeMembers(entities);
      resolvePrimaryGroups(entities);
      log.log(Level.FINE, "Ending processing of {0} entities", entities.size());
    }

    @VisibleForTesting
    Set<AdEntity> incrementalCrawl(AdServer server, long previousHighestUSN,
        long currentHighestUSN) throws InterruptedNamingException {
      log.log(Level.FINE, "Starting incremental crawl.");
      // LDAP_MATCHING_RULE_BIT_AND = 1.2.840.113556.1.4.803
      // and ADS_GROUP_TYPE_SECURITY_ENABLED = 2147483648.
      // TODO(myk): Phase II: indicate that this search should exclude members
      Set<AdEntity> newOrModifiedEntities = server.search("(&(uSNChanged>="
          + (previousHighestUSN + 1) + ")(|(&(objectClass=group)"
          + "(groupType:1.2.840.113556.1.4.803:=2147483648))"
          + "(&(objectClass=user)(objectCategory=person))))",
          /*deleted=*/ false,
          new String[] { "uSNChanged", "sAMAccountName", "objectGUID;binary",
              "objectSid;binary", "userPrincipalName", "primaryGroupId",
              "member", "userAccountControl" });
      // disabled groups handled later, in makeDefs()
      log.log(Level.FINE, "Ending incremental crawl - now starting "
          + "processing.");
      // remove previous value of newly-seen entity, if found
      for (AdEntity e : newOrModifiedEntities) {
        AdEntity oldEntity = bySid.get(e.getSid());
        if (oldEntity != null) {
          entities.remove(oldEntity);
          byDn.remove(oldEntity.getDn());
          members.remove(oldEntity);
          wellKnownMembership.get(everyone).remove(oldEntity.getDn());
        }
      }
      // add the new-or-modified entries to our catalog
      entities.addAll(newOrModifiedEntities);
      processEntities(newOrModifiedEntities, server.getnETBIOSName());
      log.log(Level.FINE, "Ending incremental crawl.");
      return newOrModifiedEntities;
    }

    /**
     * Correctly specify each group's members in the "members" data store
     */
    private void initializeMembers(Set<AdEntity> entities) {
      for (AdEntity entity : entities) {
        if (entity.isGroup()) {
          members.put(entity, new TreeSet<String>(entity.getMembers()));
        }
      }
    }

    /**
     * Make sure that each non-group entity's "primary" group exists in bySid
     *
     * and contains that entity in the <code>members</code> data store.
     */
    private void resolvePrimaryGroups(Set<AdEntity> entities) {
      int nadds = 0;
      int missingGroups = 0;
      for (AdEntity e : entities) {
        if (e.isGroup()) {
          continue;
        }
        AdEntity user = e;
        AdEntity primaryGroup = bySid.get(user.getPrimaryGroupSid());
        if (primaryGroup == null) {
          missingGroups++;
          log.log(Level.WARNING,
              "Group {0} -- primary group for user {1} -- not found",
              new Object[]{user.getPrimaryGroupSid(), user});
          continue;
        }
        if (!members.containsKey(primaryGroup)) {
          members.put(primaryGroup, new TreeSet<String>());
        }
        members.get(primaryGroup).add(user.getDn());
        wellKnownMembership.get(everyone).add(user.getDn());
        nadds++;
      }
      log.log(Level.FINE, "# primary groups: {0}", members.keySet().size());
      if (missingGroups > 0) {
        log.log(Level.FINE, "# missing primary groups: {0}", missingGroups);
      }
      log.log(Level.FINE, "# users added to all primary groups: {0}", nadds);
    }

    void resolveForeignSecurityPrincipals() {
      //TODO(myk) Phase II: pass in only the entities just read in (for an
      // incremental search to only consider those entities)
      int nGroups = 0;
      int nNullSid = 0;
      int nNullResolution = 0;
      int nResolved = 0;
      for (AdEntity entity : entities) {
        if (!entity.isGroup() || entity.isWellKnown()) {
          continue;
        }
        nGroups++;
        Set<String> resolvedMembers = new HashSet<String>();
        for (String member : members.get(entity)) {
          String sid = AdEntity.parseForeignSecurityPrincipal(member);
          if (null == sid) {
            resolvedMembers.add(member);
            nNullSid++;
          } else {
            AdEntity resolved = bySid.get(sid);
            if (null == resolved) {
              log.info("unable to resolve foreign principal ["
                  + member + "]; member of [" + entity.getDn());
              nNullResolution++;
            } else {
              resolvedMembers.add(resolved.getDn());
              nResolved++;
            }
          }
        }
        members.put(entity, resolvedMembers);
      }
      log.log(Level.FINE, "#groups: {0}", nGroups);
      log.log(Level.FINE, "#null-SID: {0}", nNullSid);
      log.log(Level.FINE, "#null-resolve: {0}", nNullResolution);
      log.log(Level.FINE, "#resolved: {0}", nResolved);
    }

    Map<GroupPrincipal, List<Principal>> makeDefs() {
      // Merge members with well known group members
      //TODO(myk) Phase II: pass in only the entities just read in (for an
      // incremental search to only consider those entities)
      Map<AdEntity, Set<String>> allMembers
          = new HashMap<AdEntity, Set<String>>(members);
      allMembers.putAll(wellKnownMembership);
      Map<GroupPrincipal, List<Principal>> groups
          = new HashMap<GroupPrincipal, List<Principal>>();
      for (AdEntity entity : entities) {
        if (!entity.isGroup()) {
          continue;
        }

        if (!allMembers.containsKey(entity)) {
          continue;
        }

        String groupName = getPrincipalName(entity);
        GroupPrincipal group;
        try {
          group = new GroupPrincipal(groupName, namespace);
        } catch (IllegalArgumentException iae) {
          log.log(Level.WARNING, "Skipping over badly-named group", iae);
          continue;
        }
        List<Principal> def = new ArrayList<Principal>();

        if (!feedBuiltinGroups
            && entity.getSid().startsWith("S-1-5-32-")) {
          log.log(Level.FINER, "Sending empty BUILTIN Group {0}", entity);
          groups.put(group, def);
          continue;
        }

        if (entity.isDisabled()) {
          log.log(Level.FINE, "Skipping {0} members from disabled group {1}",
              new Object[]{entity.getMembers().size(), group});
          groups.put(group, def);
          continue;
        }
        for (String memberDn : allMembers.get(entity)) {
          AdEntity member = byDn.get(memberDn);
          if (member == null) {
            log.info("Unknown member [" + memberDn + "] of group ["
                + entity.getDn());
            continue;
          }
          Principal p;
          String memberName = getPrincipalName(member);
          if (member.isGroup()) {
            try {
              p = new GroupPrincipal(memberName, namespace);
            } catch (IllegalArgumentException iae) {
              String warning = "Skipping badly-named group \"" + memberName
                  + "\" from group \"" + groupName + "\".";
              log.log(Level.WARNING, warning, iae);
              continue;
            }
          } else {
            try {
              p = new UserPrincipal(memberName, namespace);
            } catch (IllegalArgumentException iae) {
              String warning = "Skipping badly-named user \"" + memberName
                  + "\" from group \"" + groupName + "\".";
              log.log(Level.WARNING, warning, iae);
              continue;
            }
          }
          def.add(p);
        }
        if (entity.isWellKnown()) {
          log.log(Level.FINE, "Well known group {0} with # members {1}",
              new Object[]{group, def.size()});
        }
        groups.put(group, def);
      }
      log.log(Level.FINE, "number of groups defined: {0}",
           groups.keySet().size());
      if (log.isLoggable(Level.FINER)) {
        int numGroups = groups.keySet().size();
        int totalMembers = 0;
        for (List<Principal> def : groups.values()) {
          totalMembers += def.size();
        }
        if (0 != numGroups) {
          double mean = ((double) totalMembers) / numGroups;
          log.finer("mean size of defined group: " + mean);
        }
      }
      return groups;
    }

    /*
     * returns principal name for ADEntity object. if domain is available return
     * principal name as samaccountname@domain else just use samaccountname as
     * principal name.
     */
    String getPrincipalName(AdEntity e) {
      return domain.get(e) != null ?
          e.getSAMAccountName() + "@" + domain.get(e) : e.getSAMAccountName();
    }

    /* Combines info of another catalog with this one. */
    void add(GroupCatalog other) {
      entities.addAll(other.entities);
      members.putAll(other.members);
      bySid.putAll(other.bySid);
      byDn.putAll(other.byDn);
      domain.putAll(other.domain);
      for (Object o : wellKnownMembership.keySet()) {
        wellKnownMembership.get(o).addAll(other.wellKnownMembership.get(o));
      }
    }

    void clear() {
      entities.clear();
      members.clear();
      bySid.clear();
      byDn.clear();
      domain.clear();
      wellKnownMembership.clear();
    }

    @Override
    public int hashCode() {
      return Arrays.hashCode(
          new Object[] {entities, members, bySid, byDn, domain});
    }

    @Override
    public boolean equals(Object o) {
      if (!(o instanceof GroupCatalog)) {
        return false;
      }
      GroupCatalog gc = (GroupCatalog) o;
      return entities.equals(gc.entities)
          && members.equals(gc.members)
          && bySid.equals(gc.bySid)
          && byDn.equals(gc.byDn)
          && domain.equals(gc.domain)
          && wellKnownMembership.equals(gc.wellKnownMembership);
    }
  }
}
