// Path: src/main/java/com/google/enterprise/cloudsearch/sharepoint/ActiveDirectoryPrincipal.java
// static enum PrincipalFormat {
//   NONE,
//   DNS,
//   NETBIOS,
//   ;
// 
//   String format(String plainName, String domain) {
//     checkArgument(
//         !Strings.isNullOrEmpty(domain) || this == PrincipalFormat.NONE,
//         "Domain can not be empty if PrincipalFormat is not NONE");
//     switch (this) {
//       case NONE:
//         return plainName;
//       case DNS:
//         return plainName + "@" + domain;
//       case NETBIOS:
//         return domain + "\\" + plainName;
//       default:
//         throw new AssertionError("Unsupported PrincipalFormat " + this);
//     }
//   }
// }


import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.enterprise.cloudsearch.sdk.config.Configuration;
import com.google.enterprise.cloudsearch.sharepoint.ActiveDirectoryPrincipal.PrincipalFormat;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.CommunicationException;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
    @Override
    public Optional<String> getUserAccountBySid(String sid) throws IOException {
      try {
        Optional<SearchResult> results = getSidLookupResult(sid);
        if (!results.isPresent()) {
          return Optional.empty();
        }
        SearchResult sr = results.get();
        Attributes attrbs = sr.getAttributes();
        // use sAMAccountName when available
        String sAMAccountName = (String) getAttribute(attrbs, ATTR_SAMACCOUNTNAME);
        if (!Strings.isNullOrEmpty(sAMAccountName)) {
          return Optional.of(sAMAccountName);
        }
        log.log(Level.FINER, "sAMAccountName is null for SID {0}. This might"
            + " be domain object.", sid);
        String name = (String) getAttribute(attrbs, ATTR_NAME);
        if (Strings.isNullOrEmpty(name)) {
          log.log(Level.WARNING, "name is null for SID {0}. Returing empty.", sid);
          return Optional.empty();
        }
        return Optional.of(name);
      } catch (NamingException ne) {
        throw new IOException(ne);
      }
    }

    @Override
    public Optional<String> getEmailByPrincipal(ActiveDirectoryPrincipal principal)
        throws IOException {
// Path: src/main/java/com/google/enterprise/cloudsearch/sharepoint/ActiveDirectoryPrincipal.java
// static enum PrincipalFormat {
//   NONE,
//   DNS,
//   NETBIOS,
//   ;
// 
//   String format(String plainName, String domain) {
//     checkArgument(
//         !Strings.isNullOrEmpty(domain) || this == PrincipalFormat.NONE,
//         "Domain can not be empty if PrincipalFormat is not NONE");
//     switch (this) {
//       case NONE:
//         return plainName;
//       case DNS:
//         return plainName + "@" + domain;
//       case NETBIOS:
//         return domain + "\\" + plainName;
//       default:
//         throw new AssertionError("Unsupported PrincipalFormat " + this);
//     }
//   }
// }


// Path: src/main/java/com/google/enterprise/cloudsearch/sharepoint/ActiveDirectoryClient.java
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.enterprise.cloudsearch.sdk.config.Configuration;
import com.google.enterprise.cloudsearch.sharepoint.ActiveDirectoryPrincipal.PrincipalFormat;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.CommunicationException;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;

    @Override
    public Optional<String> getUserAccountBySid(String sid) throws IOException {
      try {
        Optional<SearchResult> results = getSidLookupResult(sid);
        if (!results.isPresent()) {
          return Optional.empty();
        }
        SearchResult sr = results.get();
        Attributes attrbs = sr.getAttributes();
        // use sAMAccountName when available
        String sAMAccountName = (String) getAttribute(attrbs, ATTR_SAMACCOUNTNAME);
        if (!Strings.isNullOrEmpty(sAMAccountName)) {
          return Optional.of(sAMAccountName);
        }
        log.log(Level.FINER, "sAMAccountName is null for SID {0}. This might"
            + " be domain object.", sid);
        String name = (String) getAttribute(attrbs, ATTR_NAME);
        if (Strings.isNullOrEmpty(name)) {
          log.log(Level.WARNING, "name is null for SID {0}. Returing empty.", sid);
          return Optional.empty();
        }
        return Optional.of(name);
      } catch (NamingException ne) {
        throw new IOException(ne);
      }
    }

    @Override
    public Optional<String> getEmailByPrincipal(ActiveDirectoryPrincipal principal)
        throws IOException {
      if (principal.getFormat() == PrincipalFormat.NETBIOS) {