// Copyright 2012 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.sharepoint;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Multimap;
import com.google.common.collect.TreeMultimap;
import com.google.enterprise.adaptor.AbstractAdaptor;
import com.google.enterprise.adaptor.Acl;
import com.google.enterprise.adaptor.AdaptorContext;
import com.google.enterprise.adaptor.Config;
import com.google.enterprise.adaptor.DocId;
import com.google.enterprise.adaptor.DocIdEncoder;
import com.google.enterprise.adaptor.DocIdPusher;
import com.google.enterprise.adaptor.GroupPrincipal;
import com.google.enterprise.adaptor.IOHelper;
import com.google.enterprise.adaptor.InvalidConfigurationException;
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.StartupException;
import com.google.enterprise.adaptor.UserPrincipal;
import com.google.enterprise.adaptor.sharepoint.RareModificationCache.CachedList;
import com.google.enterprise.adaptor.sharepoint.RareModificationCache.CachedVirtualServer;
import com.google.enterprise.adaptor.sharepoint.RareModificationCache.CachedWeb;
import com.google.enterprise.adaptor.sharepoint.SamlAuthenticationHandler.SamlHandshakeManager;
import com.google.enterprise.adaptor.sharepoint.SiteDataClient.CursorPaginator;
import com.google.enterprise.adaptor.sharepoint.SiteDataClient.Paginator;
import com.google.enterprise.adaptor.sharepoint.SiteDataClient.XmlProcessingException;

import com.microsoft.schemas.sharepoint.soap.ContentDatabase;
import com.microsoft.schemas.sharepoint.soap.ContentDatabases;
import com.microsoft.schemas.sharepoint.soap.Files;
import com.microsoft.schemas.sharepoint.soap.FolderData;
import com.microsoft.schemas.sharepoint.soap.Folders;
import com.microsoft.schemas.sharepoint.soap.GroupMembership;
import com.microsoft.schemas.sharepoint.soap.Item;
import com.microsoft.schemas.sharepoint.soap.ItemData;
import com.microsoft.schemas.sharepoint.soap.Lists;
import com.microsoft.schemas.sharepoint.soap.ObjectType;
import com.microsoft.schemas.sharepoint.soap.Permission;
import com.microsoft.schemas.sharepoint.soap.PolicyUser;
import com.microsoft.schemas.sharepoint.soap.SPContentDatabase;
import com.microsoft.schemas.sharepoint.soap.SPList;
import com.microsoft.schemas.sharepoint.soap.SPListItem;
import com.microsoft.schemas.sharepoint.soap.SPSite;
import com.microsoft.schemas.sharepoint.soap.SPWeb;
import com.microsoft.schemas.sharepoint.soap.Scopes;
import com.microsoft.schemas.sharepoint.soap.Site;
import com.microsoft.schemas.sharepoint.soap.SiteDataSoap;
import com.microsoft.schemas.sharepoint.soap.Sites;
import com.microsoft.schemas.sharepoint.soap.TrueFalseType;
import com.microsoft.schemas.sharepoint.soap.UserDescription;
import com.microsoft.schemas.sharepoint.soap.VirtualServer;
import com.microsoft.schemas.sharepoint.soap.Web;
import com.microsoft.schemas.sharepoint.soap.Webs;
import com.microsoft.schemas.sharepoint.soap.Xml;
import com.microsoft.schemas.sharepoint.soap.authentication.AuthenticationSoap;
import com.microsoft.schemas.sharepoint.soap.directory.GetUserCollectionFromSiteResponse;
import com.microsoft.schemas.sharepoint.soap.directory.GetUserCollectionFromSiteResponse.GetUserCollectionFromSiteResult;
import com.microsoft.schemas.sharepoint.soap.directory.User;
import com.microsoft.schemas.sharepoint.soap.directory.UserGroupSoap;
import com.microsoft.schemas.sharepoint.soap.people.ArrayOfPrincipalInfo;
import com.microsoft.schemas.sharepoint.soap.people.ArrayOfString;
import com.microsoft.schemas.sharepoint.soap.people.PeopleSoap;
import com.microsoft.schemas.sharepoint.soap.people.PrincipalInfo;
import com.microsoft.schemas.sharepoint.soap.people.SPPrincipalType;

import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.io.IOException;
import java.io.InputStream;
import java.net.Authenticator;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.EndpointReference;
import javax.xml.ws.Holder;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.wsaddressing.W3CEndpointReferenceBuilder;

/**
 * SharePoint Adaptor for the GSA.
 */
public class SharePointAdaptor extends AbstractAdaptor
    implements PollingIncrementalLister {
  /** Charset used in generated HTML responses. */
  private static final Charset CHARSET = Charset.forName("UTF-8");
  private static final String XMLNS_DIRECTORY
      = "http://schemas.microsoft.com/sharepoint/soap/directory/";
  
  /** SharePoint's namespace. */
  private static final String XMLNS
      = "http://schemas.microsoft.com/sharepoint/soap/";

  /**
   * The data element within a self-describing XML blob. See
   * http://msdn.microsoft.com/en-us/library/windows/desktop/ms675943.aspx .
   */
  private static final QName DATA_ELEMENT
      = new QName("urn:schemas-microsoft-com:rowset", "data");
  /**
   * The row element within a self-describing XML blob. See
   * http://msdn.microsoft.com/en-us/library/windows/desktop/ms675943.aspx .
   */
  private static final QName ROW_ELEMENT = new QName("#RowsetSchema", "row");
  /**
   * Row attribute guaranteed to be in ListItem responses. See
   * http://msdn.microsoft.com/en-us/library/dd929205.aspx . Provides ability to
   * distinguish between folders and other list items.
   */
  private static final String OWS_FSOBJTYPE_ATTRIBUTE = "ows_FSObjType";
  private static final String OWS_AUTHOR_ATTRIBUTE = "ows_Author";
  /** Row attribute that contains the title of the List Item. */
  private static final String OWS_TITLE_ATTRIBUTE = "ows_Title";
  /**
   * Row attribute that contains a URL-like string identifying the object.
   * Sometimes this can be modified (by turning spaces into %20 and the like) to
   * access the object. In general, this in the string we provide to SP to
   * resolve information about the object.
   */
  private static final String OWS_SERVERURL_ATTRIBUTE = "ows_ServerUrl";
  /**
   * Row attribute that contains a hierarchial hex number that describes the
   * type of object. See http://msdn.microsoft.com/en-us/library/aa543822.aspx
   * for more information about content type IDs.
   */
  private static final String OWS_CONTENTTYPEID_ATTRIBUTE = "ows_ContentTypeId";
  /**
   * Row attribute guaranteed to be in ListItem responses. See
   * http://msdn.microsoft.com/en-us/library/dd929205.aspx . Provides scope id
   * used for permissions. Note that the casing is different than documented;
   * this is simply because of a documentation bug.
   */
  private static final String OWS_SCOPEID_ATTRIBUTE = "ows_ScopeId";
  private static final String OWS_FILEDIRREF_ATTRIBUTE = "ows_FileDirRef";
  /**
   * As described at http://msdn.microsoft.com/en-us/library/aa543822.aspx .
   */
  private static final String CONTENTTYPEID_DOCUMENT_PREFIX = "0x0101";
  /** Provides the number of attachments the list item has. */
  private static final String OWS_ATTACHMENTS_ATTRIBUTE = "ows_Attachments";
  /** The last time metadata or content was modified. */
  private static final String OWS_LAST_MODIFIED_ATTRIBUTE
      = "ows_Last_x0020_Modified";
  /**
   * Matches a SP-encoded value that contains one or more values. See {@link
   * SiteAdaptor.addMetadata}.
   */
  private static final Pattern ALTERNATIVE_VALUE_PATTERN
      = Pattern.compile("^\\d+;#");
  /**
   * As defined at http://msdn.microsoft.com/en-us/library/ee394878.aspx .
   */
  private static final long VIEW_LIST_ITEMS_MASK = 0x0000000000000001;
  /**
   * As defined at http://msdn.microsoft.com/en-us/library/ee394878.aspx .
   */
  private static final long OPEN_MASK = 0x0000000000010000;
  /**
   * As defined at http://msdn.microsoft.com/en-us/library/ee394878.aspx .
   */
  private static final long VIEW_PAGES_MASK = 0x0000000000020000;
  /**
   * As defined at http://msdn.microsoft.com/en-us/library/ee394878.aspx .
   */
  private static final long MANAGE_LIST_MASK = 0x0000000000000800;

  static final long LIST_ITEM_MASK
      = OPEN_MASK | VIEW_PAGES_MASK | VIEW_LIST_ITEMS_MASK;
  private static final long READ_SECURITY_LIST_ITEM_MASK
      = OPEN_MASK | VIEW_PAGES_MASK | VIEW_LIST_ITEMS_MASK | MANAGE_LIST_MASK;

  private static final int LIST_READ_SECURITY_ENABLED = 2;

  private static final String IDENTITY_CLAIMS_PREFIX = "i:0";

  private static final String OTHER_CLAIMS_PREFIX = "c:0";
  
  private static final String METADATA_OBJECT_TYPE = "google:objecttype";
  private static final String METADATA_PARENT_WEB_TITLE 
      = "sharepoint:parentwebtitle";
  private static final String METADATA_LIST_GUID = "sharepoint:listguid";

  private static final Pattern METADATA_ESCAPE_PATTERN
      = Pattern.compile("_x([0-9a-f]{4})_");

  private static final Pattern INTEGER_PATTERN = Pattern.compile("[0-9]+");

  private static final String HTML_NAME = "[a-zA-Z:_][a-zA-Z:_0-9.-]*";
  private static final Pattern HTML_TAG_PATTERN
      = Pattern.compile(
          // Tag and attributes
          "<" + HTML_NAME + "(?:[ \n\t]+" + HTML_NAME + "="
            // Attribute values
            + "(?:'[^']*'|\"[^\"]*\"|[a-zA-Z0-9._:-]*))*[ \n\t]*/?>"
          // Close tags
          + "|</" + HTML_NAME + ">", Pattern.DOTALL);
  private static final Pattern HTML_ENTITY_PATTERN
      = Pattern.compile("&(#[0-9]+|[a-zA-Z0-9]+);");
  private static final Map<String, String> HTML_ENTITIES;
  static {
    HashMap<String, String> map = new HashMap<String, String>();
    map.put("quot", "\"");
    map.put("amp", "&");
    map.put("lt", "<");
    map.put("gt", ">");
    map.put("nbsp", "\u00a0");
    map.put("apos", "'");
    HTML_ENTITIES = Collections.unmodifiableMap(map);
  }

  private static final String SITE_COLLECTION_ADMIN_FRAGMENT = "admin";

  private int socketTimeoutMillis;
  private int readTimeOutMillis;

  /**
   * Mapping of mime-types used by SharePoint to ones that the GSA comprehends.
   */
  private static final Map<String, String> MIME_TYPE_MAPPING;
  static {
    Map<String, String> map = new HashMap<String, String>();
    // Mime types used by SharePoint that aren't IANA-registered.
    // Extension .xlsx
    map.put("application/vnd.ms-excel.12",
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    // Extension .pptx
    map.put("application/vnd.ms-powerpoint.presentation.12", "application/"
        + "vnd.openxmlformats-officedocument.presentationml.presentation");
    // Extension .docx
    map.put("application/vnd.ms-word.document.12", "application/"
        + "vnd.openxmlformats-officedocument.wordprocessingml.document");
    // Extension .ppsm
    map.put("application/vnd.ms-powerpoint.show.macroEnabled.12", "application/"
        + "vnd.openxmlformats-officedocument.presentationml.presentation");
    // Extension .ppsx
    map.put("application/vnd.ms-powerpoint.show.12", "application/"
        + "vnd.openxmlformats-officedocument.presentationml.presentation");
    // Extension .pptm
    map.put("application/vnd.ms-powerpoint.macroEnabled.12", "application/"
        + "vnd.openxmlformats-officedocument.presentationml.presentation");
    // Extension .xlsm
    map.put("application/vnd.ms-excel.macroEnabled.12",
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

    // IANA-registered mime types unknown to GSA 7.2.
    // Extension .docm
    map.put("application/vnd.ms-word.document.macroEnabled.12", "application/"
        + "vnd.openxmlformats-officedocument.wordprocessingml.document");
    // Extension .pptm
    map.put("application/vnd.ms-powerpoint.presentation.macroEnabled.12",
        "application/"
        + "vnd.openxmlformats-officedocument.presentationml.presentation");
    // Extension .xlsm
    map.put("application/vnd.ms-excel.sheet.macroEnabled.12",
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

    MIME_TYPE_MAPPING = Collections.unmodifiableMap(map);
  }

  private static final Logger log
      = Logger.getLogger(SharePointAdaptor.class.getName());

  /**
   * Map from Site or Web URL to SiteAdaptor object used to communicate with
   * that Site/Web.
   */
  private final ConcurrentMap<String, SiteAdaptor> siteAdaptors
      = new ConcurrentSkipListMap<String, SiteAdaptor>();
  private final DocId virtualServerDocId = new DocId("");
  private AdaptorContext context;
  /**
   * The URL of the top-level Virtual Server that we use to bootstrap our
   * SP instance knowledge.
   */
  private String virtualServer;
  /**
   * Cache that provides immutable {@link MemberIdMapping} instances for the
   * provided site URL key. Since {@code MemberIdMapping} is immutable, updating
   * the cache creates new mapping instances that replace the previous value.
   */
  private LoadingCache<String, MemberIdMapping> memberIdsCache
      = CacheBuilder.newBuilder()
        .refreshAfterWrite(30, TimeUnit.MINUTES)
        .expireAfterWrite(45, TimeUnit.MINUTES)
        .build(new MemberIdsCacheLoader());
  private LoadingCache<String, MemberIdMapping> siteUserCache
      = CacheBuilder.newBuilder()
        .refreshAfterWrite(30, TimeUnit.MINUTES)
        .expireAfterWrite(45, TimeUnit.MINUTES)
        .build(new SiteUserCacheLoader());
  private RareModificationCache rareModCache;
  /** Map from Content Database GUID to last known Change Token for that DB. */
  private final ConcurrentSkipListMap<String, String> contentDatabaseChangeId
      = new ConcurrentSkipListMap<String, String>();
  private final SoapFactory soapFactory;
  /** Client for initiating raw HTTP connections. */
  private final HttpClient httpClient;
  private final Callable<ExecutorService> executorFactory;

  private final AuthenticationClientFactory authenticationClientFactory;
  private ExecutorService executor;
  private boolean xmlValidation;
  private int feedMaxUrls;
  private long maxIndexableSize;
  
  private ScheduledThreadPoolExecutor scheduledExecutor;
  private String defaultNamespace;
  /** Authenticator instance that authenticates with SP. */
  /**
   * Cached value of whether we are talking to a SP 2007 server or not. This
   * value is used in case of error in certain situations.
   */
  private boolean isSp2007;
  private NtlmAuthenticator ntlmAuthenticator;
  /**
   * Lock for refreshing MemberIdMapping. We use a unique lock because it is
   * held while waiting on I/O.
   */
  private final Object refreshMemberIdMappingLock = new Object();
  
  private FormsAuthenticationHandler authenticationHandler;
  private static final TimeZone gmt = TimeZone.getTimeZone("GMT");
  /** RFC 822 date format, as updated by RFC 1123. */
  private final ThreadLocal<DateFormat> dateFormatRfc1123
      = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
          DateFormat df = new SimpleDateFormat(
              "EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH);
          df.setTimeZone(gmt);
          return df;
        }
      };
  private final ThreadLocal<DateFormat> modifiedDateFormat
      = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
          DateFormat df = new SimpleDateFormat(
              "yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH);
          df.setTimeZone(gmt);
          return df;
        }
      };
  private final ThreadLocal<DateFormat> listLastModifiedDateFormat
      = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
          DateFormat df = new SimpleDateFormat(
              "yyyy-MM-dd HH:mm:ss'Z'", Locale.ENGLISH);
          df.setTimeZone(gmt);
          return df;
        }
      };

  public SharePointAdaptor() {
    this(new SoapFactoryImpl(), new HttpClientImpl(),
        new CachedThreadPoolFactory(), new AuthenticationClientFactoryImpl());
  }

  @VisibleForTesting
  SharePointAdaptor(SoapFactory soapFactory, HttpClient httpClient,
      Callable<ExecutorService> executorFactory,
      AuthenticationClientFactory authenticationClientFactory) {
    if (soapFactory == null || httpClient == null || executorFactory == null 
        || authenticationClientFactory == null) {
      throw new NullPointerException();
    }
    this.soapFactory = soapFactory;
    this.httpClient = httpClient;
    this.executorFactory = executorFactory;
    this.authenticationClientFactory = authenticationClientFactory;
  }

  /**
   * Method to cause static initialization of the class. Mainly useful to tests
   * so that the cost of initializing the class does not count toward the first
   * test case run.
   */
  @VisibleForTesting
  static void init() {}

  @Override
  public void initConfig(Config config) {
    boolean onWindows = System.getProperty("os.name").contains("Windows");
    config.addKey("sharepoint.server", null);
    // When running on Windows, Windows Authentication can log us in.
    config.addKey("sharepoint.username", onWindows ? "" : null);
    config.addKey("sharepoint.password", onWindows ? "" : null);
    // On any particular SharePoint instance, we expect that at least some
    // responses will not pass xml validation. We keep the option around to
    // allow us to improve the schema itself, but also allow enable users to
    // enable checking as a form of debugging.
    config.addKey("sharepoint.xmlValidation", "false");
    // 2 MB. We need to know how much of the generated HTML the GSA will index,
    // because the GSA won't see links outside of that content.
    config.addKey("sharepoint.maxIndexableSize", "2097152");
    config.addKey("adaptor.namespace", "Default");
    // When running against ADFS authentication, set this to ADFS endpoint.
    config.addKey("sharepoint.sts.endpoint", "");
    // When running against ADFS authentication, set this to realm value.
    // Normally realm value is either http://sharepointurl/_trust or
    // urn:sharepointenv:com format. You can use 
    // Get-SPTrustedIdentityTokenIssuer to get "DefaultProviderRealm" value
    config.addKey("sharepoint.sts.realm", "");
    // You can override default value of http://sharepointurl/_trust by 
    // specifying this property.
    config.addKey("sharepoint.sts.trustLocation", "");
    // You can override default value of 
    // http://sharepointurl/_layouts/Authenticate.aspx by specifying this 
    // property.
    config.addKey("sharepoint.sts.login", "");
    // Set this to true when using Live authentication.
    config.addKey("sharepoint.useLiveAuthentication", "false");
  }

  @Override
  public void init(AdaptorContext context) throws Exception {
    this.context = context;
    context.setPollingIncrementalLister(this);
    Config config = context.getConfig();
    virtualServer = config.getValue("sharepoint.server");
    if (virtualServer.endsWith("/")) {
      virtualServer = virtualServer.substring(0, virtualServer.length() - 1);
    }
    String username = config.getValue("sharepoint.username");
    String password = context.getSensitiveValueDecoder().decodeValue(
        config.getValue("sharepoint.password"));
    xmlValidation = Boolean.parseBoolean(
        config.getValue("sharepoint.xmlValidation"));
    feedMaxUrls = Integer.parseInt(config.getValue("feed.maxUrls"));
    maxIndexableSize = Integer.parseInt(
        config.getValue("sharepoint.maxIndexableSize"));
    defaultNamespace = config.getValue("adaptor.namespace");
    String stsendpoint = config.getValue("sharepoint.sts.endpoint");
    String stsrealm = config.getValue("sharepoint.sts.realm");
    boolean useLiveAuthentication = Boolean.parseBoolean(
        config.getValue("sharepoint.useLiveAuthentication"));
    socketTimeoutMillis = Integer.parseInt(
        config.getValue("adaptor.docHeaderTimeoutSecs")) * 1000;
    readTimeOutMillis = Integer.parseInt(
        config.getValue("adaptor.docContentTimeoutSecs")) * 1000;

    log.log(Level.CONFIG, "VirtualServer: {0}", virtualServer);
    log.log(Level.CONFIG, "Username: {0}", username);
    log.log(Level.CONFIG, "Password: {0}", password);
    log.log(Level.CONFIG, "Default Namespace: {0}", defaultNamespace);
    log.log(Level.CONFIG, "STS Endpoint: {0}", stsendpoint);
    log.log(Level.CONFIG, "STS Realm: {0}", stsrealm);
    log.log(Level.CONFIG, "Use Live Authentication: {0}",
        useLiveAuthentication);

    ntlmAuthenticator = new NtlmAuthenticator(username, password);
    // Unfortunately, this is a JVM-wide modification.
    Authenticator.setDefault(ntlmAuthenticator);
    URL virtualServerUrl = new URL(virtualServer);
    ntlmAuthenticator.addPermitForHost(virtualServerUrl);
    scheduledExecutor = new ScheduledThreadPoolExecutor(1);
    String authenticationType;
    if (useLiveAuthentication)  {
      if ("".equals(username) || "".equals(password)) {
        throw new InvalidConfigurationException("Adaptor is configured to "
            + "use Live authentication. Please specify valid username "
            + "and password.");
      }
      SamlHandshakeManager manager = authenticationClientFactory
          .newLiveAuthentication(virtualServer, username, password);
      authenticationHandler = new SamlAuthenticationHandler.Builder(username,
          password, scheduledExecutor, manager).build();     
      authenticationType = "Live";
    } else if (!"".equals(stsendpoint) && !"".equals(stsrealm)) {
      if ("".equals(username) || "".equals(password)) {
        throw new InvalidConfigurationException("Adaptor is configured to "
            + "use ADFS authentication. Please specify valid username "
            + "and password.");
      }
      SamlHandshakeManager manager = authenticationClientFactory
          .newAdfsAuthentication(virtualServer, username, password, stsendpoint,
              stsrealm, config.getValue("sharepoint.sts.login"),
              config.getValue("sharepoint.sts.trustLocation"));
      authenticationHandler = new SamlAuthenticationHandler.Builder(username,
          password, scheduledExecutor, manager).build();            
      authenticationType = "ADFS";
    } else {    
      AuthenticationSoap authenticationSoap = authenticationClientFactory
          .newSharePointFormsAuthentication(virtualServer, username, password);
      addSocketTimeoutConfiguration((BindingProvider) authenticationSoap);
      authenticationHandler = new SharePointFormsAuthenticationHandler
          .Builder(username, password, scheduledExecutor, authenticationSoap)
          .build();
      authenticationType = "SharePoint";
    }
    
    try {
      log.log(Level.INFO, "Using {0} authentication.", authenticationType);
      authenticationHandler.start();      
    } catch (IOException ex) {
      if (ex instanceof UnknownHostException) {
       // This may be due to  DNS issue or transiant network error.
       // Just rethrow excption and allow adaptor to retry.
       throw ex; 
      }
      
      if (ex instanceof ConnectException) {
        // SharePoint might be down. Just rethrow exception and allow adaptor to
        // retry.
        throw ex;
      }
      String adfsWarning = "ADFS".equals(authenticationType) 
          ? " Also verify if stsendpoint and stsrealm is specified correctly "
          + "and ADFS environment is available." : "";
      String warning = String.format(
          "Failed to start adaptor using %s authentication."
          + " Please verify adaptor configuration for SharePoint url,"
          + " username and password.%s", authenticationType, adfsWarning);
      throw new StartupException(warning, ex);
    }
   
    try {
      executor = executorFactory.call();
      SiteAdaptor vsAdaptor = getSiteAdaptor(virtualServer, virtualServer);
      SiteDataClient virtualServerSiteDataClient =
          vsAdaptor.getSiteDataClient();
      rareModCache
          = new RareModificationCache(virtualServerSiteDataClient, executor);

      // Test out configuration.
      VirtualServer vs = virtualServerSiteDataClient.getContentVirtualServer();
      String version = vs.getMetadata().getVersion();
      log.log(Level.INFO, "SharePoint Version : {0}", version);
      // Version is missing for SP 2007 (but its version is 12).
      // Version for SP2010 is 14. Version for SP2013 is 15.
      isSp2007 = (version == null);
      log.log(Level.FINE, "isSP2007 : {0}", isSp2007);
      
      // Loop through all host-named site collections and add them to
      // whitelist for authenticator.
      for (ContentDatabases.ContentDatabase cdcd : 
          vs.getContentDatabases().getContentDatabase()) {
        ContentDatabase cd;
        try {
          cd = virtualServerSiteDataClient.getContentContentDatabase(
              cdcd.getID(), true);
        } catch (IOException ex) {
          log.log(Level.WARNING, "Failed to get sites for database {0}",
              cdcd.getID());
          continue;
        }
        if (cd.getSites() == null) {
          continue;
        }
        for (Sites.Site siteListing : cd.getSites().getSite()) {
          String siteString
              = vsAdaptor.encodeDocId(siteListing.getURL()).getUniqueId();
          ntlmAuthenticator.addPermitForHost(spUrlToUri(siteString).toURL());
        }
      }
    } catch (WebServiceException ex) {
      String warning;
      Throwable cause = ex.getCause();
      if (cause instanceof UnknownHostException) {
        warning = String.format("Cannot find SharePoint server \"%s\" -- "
            + "please make sure it is specified properly.", virtualServer);
        // Note: even this exception should not be treated as a "Permanent
        // configuration error" -- it can be caused by transient network down
        // or DNS down.
      } else if (username.equals("")) {
        warning = String.format("Cannot connect to server \"%s\" as the "
            + "current user.  Please make sure the server is specified "
            + "correctly, and that the user has sufficient permission to "
            + "access the SharePoint server.  If the SharePoint server is "
            + "currently down, please try again later.", virtualServer);
      } else {
        warning = String.format("Cannot connect to server \"%s\" as user "
            + "\"%s\" with the specified password.  Please make sure they are "
            + "specified correctly, and that the user has sufficient "
            + "permission to access the SharePoint server.  If the SharePoint "
            + "server is currently down, please try again later.",
            virtualServer, username);
      }
      throw new IOException(warning, ex);
    } catch (Exception e) {
      // Don't leak the executor.
      destroy();
      throw e;
    }
  }

  @Override
  public void destroy() {
    shutdownExecutor(executor);
    shutdownExecutor(scheduledExecutor);    
    executor = null;
    scheduledExecutor = null;
    rareModCache = null;
    Authenticator.setDefault(null);
    ntlmAuthenticator = null;
  }

  private synchronized void shutdownExecutor(ExecutorService executor) {
    if (executor == null) {
      return;
    }
    executor.shutdown();
    try {
      executor.awaitTermination(10, TimeUnit.SECONDS);
    } catch (InterruptedException ex) {
      Thread.currentThread().interrupt();
    }
    executor.shutdownNow();
  }

  @Override
  public void getDocContent(Request request, Response response)
      throws IOException {
    log.entering("SharePointAdaptor", "getDocContent",
        new Object[] {request, response});
    DocId id = request.getDocId();
     if (id.equals(virtualServerDocId)) {
      SiteAdaptor virtualServerSiteAdaptor
          = getSiteAdaptor(virtualServer, virtualServer);
      virtualServerSiteAdaptor.getVirtualServerDocContent(request, response);
    } else {
      SiteAdaptor rootSiteAdaptor
          = getRootAdaptorForUrl(spUrlToUri(id.getUniqueId()));
      if (rootSiteAdaptor == null) {
        log.log(Level.FINE, "responding not found");
        response.respondNotFound();
        log.exiting("SharePointAdaptor", "getDocContent");
        return;
      }
      SiteAdaptor siteAdaptor
          = rootSiteAdaptor.getAdaptorForUrl(id.getUniqueId());
      if (siteAdaptor == null) {
        log.log(Level.FINE, "responding not found");
        response.respondNotFound();
        log.exiting("SharePointAdaptor", "getDocContent");
        return;
      }
      siteAdaptor.getDocContent(request, response);
    }
    log.exiting("SharePointAdaptor", "getDocContent");
  }

  @Override
  public void getDocIds(DocIdPusher pusher) throws InterruptedException,
      IOException {
    log.entering("SharePointAdaptor", "getDocIds", pusher);
    pusher.pushDocIds(Arrays.asList(virtualServerDocId));

    SiteAdaptor vsAdaptor = getSiteAdaptor(virtualServer, virtualServer);
    SiteDataClient vsClient = vsAdaptor.getSiteDataClient();
    VirtualServer vs = vsClient.getContentVirtualServer();
    Map<GroupPrincipal, Collection<Principal>> defs
        = new HashMap<GroupPrincipal, Collection<Principal>>();
    for (ContentDatabases.ContentDatabase cdcd
        : vs.getContentDatabases().getContentDatabase()) {
      ContentDatabase cd;
      try {
        cd = vsClient.getContentContentDatabase(cdcd.getID(), true);
      } catch (IOException ex) {
        log.log(Level.WARNING, "Failed to get local groups for database {0}",
            cdcd.getID());
        continue;
      }
      if (cd.getSites() == null) {
        continue;
      }
      for (Sites.Site siteListing : cd.getSites().getSite()) {
        String siteString
            = vsAdaptor.encodeDocId(siteListing.getURL()).getUniqueId();
        ntlmAuthenticator.addPermitForHost(spUrlToUri(siteString).toURL());           
        SiteAdaptor siteAdaptor = getSiteAdaptor(siteString, siteString);
        Site site;
        try {
          site = siteAdaptor.getSiteDataClient().getContentSite();
        } catch (IOException ex) {
          log.log(Level.WARNING, "Failed to get local groups for site {0}",
              siteString);
          continue;
        }
        Map<GroupPrincipal, Collection<Principal>> siteDefs
            = siteAdaptor.computeMembersForGroups(site.getGroups());
        for (Map.Entry<GroupPrincipal, Collection<Principal>> me
            : siteDefs.entrySet()) {
          defs.put(me.getKey(), me.getValue());
          if (defs.size() >= feedMaxUrls) {
            pusher.pushGroupDefinitions(defs, false);
            defs.clear();
          }
        }
      }
    }
    pusher.pushGroupDefinitions(defs, false);
    log.exiting("SharePointAdaptor", "getDocIds");
  }

  @Override
  public void getModifiedDocIds(DocIdPusher pusher)
      throws InterruptedException {
    log.entering("SharePointAdaptor", "getModifiedDocIds", pusher);
    SiteAdaptor siteAdaptor;
    try {
      siteAdaptor = getSiteAdaptor(virtualServer, virtualServer);
    } catch (IOException ex) {
      // The call should never fail, and it is the only IOException-throwing
      // call that we can't recover from. Handling it this way allows us to
      // remove IOException from the signature and ensure that we handle the
      // exception gracefully throughout this method.
      throw new RuntimeException(ex);
    }
    SiteDataClient client = siteAdaptor.getSiteDataClient();
    VirtualServer vs = null;
    try {
      vs = client.getContentVirtualServer();
    } catch (IOException ex) {
      log.log(Level.WARNING, "Could not retrieve list of content databases",
          ex);
    }
    Set<String> discoveredContentDatabases;
    if (vs == null) {
      // Retrieving list of databases failed, but we can continue without it.
      discoveredContentDatabases
        = new HashSet<String>(contentDatabaseChangeId.keySet());
    } else {
      discoveredContentDatabases = new HashSet<String>();
      if (vs.getContentDatabases() != null) {
        for (ContentDatabases.ContentDatabase cd
            : vs.getContentDatabases().getContentDatabase()) {
          discoveredContentDatabases.add(cd.getID());
        }
      }
    }
    Set<String> knownContentDatabases
        = new HashSet<String>(contentDatabaseChangeId.keySet());
    Set<String> removedContentDatabases
        = new HashSet<String>(knownContentDatabases);
    removedContentDatabases.removeAll(discoveredContentDatabases);
    Set<String> newContentDatabases
        = new HashSet<String>(discoveredContentDatabases);
    newContentDatabases.removeAll(knownContentDatabases);
    Set<String> updatedContentDatabases
        = new HashSet<String>(knownContentDatabases);
    updatedContentDatabases.retainAll(discoveredContentDatabases);
    if (!removedContentDatabases.isEmpty()
        || !newContentDatabases.isEmpty()) {
      DocIdPusher.Record record
          = new DocIdPusher.Record.Builder(virtualServerDocId)
          .setCrawlImmediately(true).build();
      pusher.pushRecords(Collections.singleton(record));
    }
    for (String contentDatabase : removedContentDatabases) {
      contentDatabaseChangeId.remove(contentDatabase);
    }
    for (String contentDatabase : newContentDatabases) {
      ContentDatabase cd;
      try {
        cd = client.getContentContentDatabase(contentDatabase, false);
      } catch (IOException ex) {
        log.log(Level.WARNING, "Could not retrieve change id for content "
            + "database: " + contentDatabase, ex);
        // Continue processing. Hope that next time works better.
        continue;
      }
      String changeId = cd.getMetadata().getChangeId();
      contentDatabaseChangeId.put(contentDatabase, changeId);
    }
    for (String contentDatabase : updatedContentDatabases) {
      String changeId = contentDatabaseChangeId.get(contentDatabase);
      if (changeId == null) {
        // The item was removed from contentDatabaseChangeId, so apparently
        // this database is gone.
        continue;
      }
      CursorPaginator<SPContentDatabase, String> changesPaginator
          = client.getChangesContentDatabase(contentDatabase, changeId,
              isSp2007);
      Set<DocId> docIds = new HashSet<DocId>();
      Set<String> updatedSiteSecurity = new HashSet<String>();
      try {
        while (true) {
          try {
            SPContentDatabase changes = changesPaginator.next();
            if (changes == null) {
              break;
            }
            getModifiedDocIdsContentDatabase(changes, docIds,
                updatedSiteSecurity);
          } catch (XmlProcessingException ex) {
            log.log(Level.WARNING, "Error parsing changes from content "
                + "database: " + contentDatabase, ex);
            // The cursor is guaranteed to be advanced past the position that
            // failed parsing, so we just ignore the failure and continue
            // looping.
          }
          contentDatabaseChangeId.put(contentDatabase,
              changesPaginator.getCursor());
        }
      } catch (IOException ex) {
        log.log(Level.WARNING, "Error getting changes from content database: "
            + contentDatabase, ex);
        // Continue processing. Hope that next time works better.
      }
      List<DocIdPusher.Record> records
          = new ArrayList<DocIdPusher.Record>(docIds.size());
      DocIdPusher.Record.Builder builder
          = new DocIdPusher.Record.Builder(new DocId("to-be-replaced-name"))
          .setCrawlImmediately(true);
      for (DocId docId : docIds) {
        records.add(builder.setDocId(docId).build());
      }
      pusher.pushRecords(records);
      if (updatedSiteSecurity.isEmpty()) {
        continue;
      }
      Map<GroupPrincipal, Collection<Principal>> groupDefs
          = new HashMap<GroupPrincipal, Collection<Principal>>();
      for (String siteUrl : updatedSiteSecurity) {
        Site site;
        try {
          site = getSiteAdaptor(siteUrl, siteUrl).getSiteDataClient()
              .getContentSite();
        } catch (IOException ex) {
          log.log(Level.WARNING, "Failed to get local groups for site {0}",
              siteUrl);
          continue;
        }
        groupDefs.putAll(siteAdaptor.computeMembersForGroups(site.getGroups()));
      }
      pusher.pushGroupDefinitions(groupDefs, false);
    }
    log.exiting("SharePointAdaptor", "getModifiedDocIds", pusher);
  }

  @VisibleForTesting
  void getModifiedDocIdsContentDatabase(SPContentDatabase changes,
      Collection<DocId> docIds,
      Collection<String> updatedSiteSecurity) throws IOException {
    log.entering("SharePointAdaptor", "getModifiedDocIdsContentDatabase",
        new Object[] {changes, docIds});
    if (!"Unchanged".equals(changes.getChange())) {
      docIds.add(virtualServerDocId);
    }
    for (SPSite site : changes.getSPSite()) {       
      getModifiedDocIdsSite(site, docIds, updatedSiteSecurity);
    }
    log.exiting("SharePointAdaptor", "getModifiedDocIdsContentDatabase");
  }

  private void getModifiedDocIdsSite(SPSite changes, Collection<DocId> docIds,
      Collection<String> updatedSiteSecurity) throws IOException {
    log.entering("SharePointAdaptor", "getModifiedDocIdsSite",
        new Object[] {changes, docIds});
    if (isModified(changes.getChange())) {
      String siteUrl = changes.getServerUrl() + changes.getDisplayUrl();
      if (siteUrl.endsWith("/")) {
        siteUrl = siteUrl.substring(0, siteUrl.length() - 1);
      }
      docIds.add(new DocId(siteUrl));
      // Add modified site to whitelist for authenticator as this might be new
      // host name site collection.
      ntlmAuthenticator.addPermitForHost(spUrlToUri(siteUrl).toURL());
      if ("UpdateSecurity".equals(changes.getChange())) {
        updatedSiteSecurity.add(siteUrl);
      }
    }
    for (SPWeb web : changes.getSPWeb()) {
      getModifiedDocIdsWeb(web, docIds);
    }
    log.exiting("SharePointAdaptor", "getModifiedDocIdsSite");
  }

  private void getModifiedDocIdsWeb(SPWeb changes, Collection<DocId> docIds) {
    log.entering("SharePointAdaptor", "getModifiedDocIdsWeb",
        new Object[] {changes, docIds});
    if (isModified(changes.getChange())) {
      String webUrl = changes.getServerUrl() + changes.getDisplayUrl();
      if (webUrl.endsWith("/")) {
        webUrl = webUrl.substring(0, webUrl.length() - 1);
      }
      docIds.add(new DocId(webUrl));
    }
    
    for (Object choice : changes.getSPFolderOrSPListOrSPFile()) {      
      if (choice instanceof SPList) {
        getModifiedDocIdsList((SPList) choice, docIds);
      }
    }
    log.exiting("SharePointAdaptor", "getModifiedDocIdsWeb");
  }

  private void getModifiedDocIdsList(SPList changes,
      Collection<DocId> docIds) {
    log.entering("SharePointAdaptor", "getModifiedDocIdsList",
        new Object[] {changes, docIds});
    if (isModified(changes.getChange())) {
      String listUrl = changes.getServerUrl() + changes.getDisplayUrl();
      docIds.add(new DocId(listUrl));
    }
    for (Object choice : changes.getSPViewOrSPListItem()) {
      // Ignore view change detection.

      if (choice instanceof SPListItem) {
        getModifiedDocIdsListItem((SPListItem) choice, docIds);
      }
    }
    log.exiting("SharePointAdaptor", "getModifiedDocIdsList");
  }

  private void getModifiedDocIdsListItem(SPListItem changes,
      Collection<DocId> docIds) {
    log.entering("SharePointAdaptor", "getModifiedDocIdsListItem",
        new Object[] {changes, docIds});
    if (isModified(changes.getChange())) {
      Object oData = changes.getListItem().getAny();
      if (!(oData instanceof Element)) {
        log.log(Level.WARNING, "Unexpected object type for data: {0}",
            oData.getClass());
      } else {
        Element data = (Element) oData;
        String serverUrl = data.getAttribute(OWS_SERVERURL_ATTRIBUTE);        
        if (serverUrl == null) {
          log.log(Level.WARNING, "Could not find server url attribute for "
              + "list item {0}", changes.getId());
        } else {
          String url = changes.getServerUrl() + serverUrl;
          docIds.add(new DocId(url));
        }
      }
    }
    log.exiting("SharePointAdaptor", "getModifiedDocIdsListItem");
  }

  private boolean isModified(String change) {
    return !"Unchanged".equals(change) && !"Delete".equals(change);
  }

  private SiteAdaptor getSiteAdaptor(String site, String web)
      throws IOException {
    if (web.endsWith("/")) {
      // Always end without a '/' for a canonical form.
      web = web.substring(0, web.length() - 1);
    }
    SiteAdaptor siteAdaptor = siteAdaptors.get(web);
    if (siteAdaptor == null) {
      if (site.endsWith("/")) {
        // Always end without a '/' for a canonical form.
        site = site.substring(0, site.length() - 1);
      }
      ntlmAuthenticator.addPermitForHost(new URL(web));
      String endpoint = spUrlToUri(web + "/_vti_bin/SiteData.asmx").toString();
      SiteDataSoap siteDataSoap = soapFactory.newSiteData(endpoint);
      
      String endpointUserGroup = spUrlToUri(site + "/_vti_bin/UserGroup.asmx")
          .toString();
      UserGroupSoap userGroupSoap = soapFactory.newUserGroup(endpointUserGroup);
      String endpointPeople = spUrlToUri(site + "/_vti_bin/People.asmx")
          .toString();
      PeopleSoap peopleSoap = soapFactory.newPeople(endpointPeople);

      addFormsAuthenticationCookies((BindingProvider) siteDataSoap);
      addFormsAuthenticationCookies((BindingProvider) userGroupSoap);
      addFormsAuthenticationCookies((BindingProvider) peopleSoap);

      addSocketTimeoutConfiguration((BindingProvider) siteDataSoap);
      addSocketTimeoutConfiguration((BindingProvider) userGroupSoap);
      addSocketTimeoutConfiguration((BindingProvider) peopleSoap);

      siteAdaptor = new SiteAdaptor(site, web, siteDataSoap, userGroupSoap,
          peopleSoap, new MemberIdMappingCallable(site),
          new SiteUserIdMappingCallable(site));
      siteAdaptors.putIfAbsent(web, siteAdaptor);
      siteAdaptor = siteAdaptors.get(web);
    }
    return siteAdaptor;
  }
  
  private void addFormsAuthenticationCookies(BindingProvider port) {
    if (authenticationHandler.getAuthenticationCookies().isEmpty()) {
      // JAX-WS RT 2.1.4 doesn't handle headers correctly and always assumes the
      // list contains precisely one entry, so we work around it here.
      disableFormsAuthentication(port);    
      return;
    }
    port.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS,
        Collections.singletonMap("Cookie", 
            authenticationHandler.getAuthenticationCookies()));
  }
  
  private void addSocketTimeoutConfiguration(BindingProvider port) {
    port.getRequestContext().put("com.sun.xml.internal.ws.connect.timeout",
        socketTimeoutMillis);
    port.getRequestContext().put("com.sun.xml.internal.ws.request.timeout",
        readTimeOutMillis);
    port.getRequestContext().put("com.sun.xml.ws.connect.timeout",
        socketTimeoutMillis);
    port.getRequestContext().put("com.sun.xml.ws.request.timeout",
        readTimeOutMillis);
  }

  private void disableFormsAuthentication(BindingProvider port) {
    port.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, 
        Collections.singletonMap("X-FORMS_BASED_AUTH_ACCEPTED", 
          Collections.singletonList("f")));
  }

  static URI spUrlToUri(String url) throws IOException {
    // Because SP is silly, the path of the URI is unencoded, but the rest of
    // the URI is correct. Thus, we split up the path from the host, and then
    // turn them into URIs separately, and then turn everything into a
    // properly-escaped string.
    String[] parts = url.split("/", 4);
    if (parts.length < 3) {
      throw new IllegalArgumentException("Too few '/'s: " + url);
    }
    String host = parts[0] + "/" + parts[1] + "/" + parts[2];
    // Host must be properly-encoded already.
    URI hostUri = URI.create(host);
    if (parts.length == 3) {
      // There was no path.
      return hostUri;
    }
    URI pathUri;
    try {
      pathUri = new URI(null, null, "/" + parts[3], null);
    } catch (URISyntaxException ex) {
      throw new IOException(ex);
    }
    return hostUri.resolve(pathUri);
  }

  /**
   * SharePoint encodes special characters as _x????_ where the ? are hex
   * digits. Each such encoding is a UTF-16 character. For example, _x0020_ is
   * space and _xFFE5_ is the fullwidth yen sign.
   */
  @VisibleForTesting
  static String decodeMetadataName(String name) {
    Matcher m = METADATA_ESCAPE_PATTERN.matcher(name);
    StringBuffer sb = new StringBuffer();
    while (m.find()) {
      char c = (char) Integer.parseInt(m.group(1), 16);
      m.appendReplacement(sb, Matcher.quoteReplacement("" + c));
    }
    m.appendTail(sb);
    return sb.toString();
  }

  public static void main(String[] args) {
    AbstractAdaptor.main(new SharePointAdaptor(), args);
  }

  private SiteAdaptor getRootAdaptorForUrl(URI uri) throws IOException {
    if (!ntlmAuthenticator.isPermittedHost(uri.toURL())) {
      log.log(Level.WARNING, "URL {0} not white listed", uri);
      return null;
    }
    String rootUrl;
    try {
       rootUrl = getRootUrl(uri);
    } catch (URISyntaxException e) {
      throw new IOException(e);
    }
    return getSiteAdaptor(rootUrl, rootUrl);
  }
  
  private String getRootUrl(URI uri) throws URISyntaxException {
    return new URI(
        uri.getScheme(), uri.getAuthority(), null, null, null).toString();
  }

  /**
   * Convert from text/html to text/plain. Although we hope for good fidelity,
   * getting the conversion perfect is not necessary.
   */
  @VisibleForTesting
  static String stripHtml(String html) {
    html = HTML_TAG_PATTERN.matcher(html).replaceAll("");
    Matcher m = HTML_ENTITY_PATTERN.matcher(html);
    StringBuffer sb = new StringBuffer();
    while (m.find()) {
      String entity = m.group(1);
      String decodedEntity;
      if (entity.startsWith("#")) {
        entity = entity.substring(1);
        try {
          // HTML entities are only in UCS-2 range, so no need to worry about
          // converting to surrogates.
          char c = (char) Integer.parseInt(entity);
          decodedEntity = Character.toString(c);
        } catch (NumberFormatException ex) {
          log.log(Level.FINE, "Could not decode entity", ex);
          decodedEntity = "";
        }
      } else {
        entity = entity.toLowerCase(Locale.ENGLISH);
        decodedEntity = HTML_ENTITIES.get(entity);
        if (decodedEntity == null) {
          decodedEntity = "";
        }
      }
      m.appendReplacement(sb, Matcher.quoteReplacement(decodedEntity));
    }
    m.appendTail(sb);
    return sb.toString();
  }

  @VisibleForTesting
  class SiteAdaptor {
    private final SiteDataClient siteDataClient;
    private final UserGroupSoap userGroup;
    private final PeopleSoap people;
    private final String siteUrl;
    private final String webUrl;
    private final DocId siteDocId;
    /**
     * Callable for accessing an up-to-date instance of {@link MemberIdMapping}.
     * Using a callable instead of accessing {@link #memberIdsCache} directly as
     * this allows mocking out the cache during testing.
     */
    private final Callable<MemberIdMapping> memberIdMappingCallable;
    private final Callable<MemberIdMapping> siteUserIdMappingCallable;

    public SiteAdaptor(String site, String web, SiteDataSoap siteDataSoap,
        UserGroupSoap userGroupSoap, PeopleSoap people,
        Callable<MemberIdMapping> memberIdMappingCallable,
        Callable<MemberIdMapping> siteUserIdMappingCallable) {
      log.entering("SiteAdaptor", "SiteAdaptor",
          new Object[] {site, web, siteDataSoap});
      if (site.endsWith("/")) {
        throw new AssertionError();
      }
      if (web.endsWith("/")) {
        throw new AssertionError();
      }
      if (memberIdMappingCallable == null) {
        throw new NullPointerException();
      }
      this.siteUrl = site;
      this.siteDocId = new DocId(site);
      this.webUrl = web;
      this.userGroup = userGroupSoap;
      this.people = people;
      this.siteDataClient = new SiteDataClient(siteDataSoap, xmlValidation);
      this.memberIdMappingCallable = memberIdMappingCallable;
      this.siteUserIdMappingCallable = siteUserIdMappingCallable;
      log.exiting("SiteAdaptor", "SiteAdaptor");
    }

    private MemberIdMapping getMemberIdMapping() throws IOException {
      try {
        return memberIdMappingCallable.call();
      } catch (IOException ex) {
        throw ex;
      } catch (Exception ex) {
        throw new IOException(ex);
      }
    }

    /**
     * Provide a more recent MemberIdMapping than {@code mapping}, because the
     * mapping is known to be out-of-date.
     */
    private MemberIdMapping refreshMemberIdMapping(MemberIdMapping mapping)
        throws IOException {
      // Synchronize callers to prevent a rush of invalidations due to multiple
      // callers noticing that the map was out of date at the same time.
      synchronized (refreshMemberIdMappingLock) {
        // NOTE: This may block on I/O, so we must be wary of what locks are
        // held.
        MemberIdMapping maybeNewMapping = getMemberIdMapping();
        if (mapping != maybeNewMapping) {
          // The map has already been refreshed.
          return maybeNewMapping;
        }
        memberIdsCache.invalidate(siteUrl);
      }
      return getMemberIdMapping();
    }

     private MemberIdMapping getSiteUserMapping() throws IOException {
      try {
        return siteUserIdMappingCallable.call();
      } catch (IOException ex) {
        throw ex;
      } catch (Exception ex) {
        throw new IOException(ex);
      }
    }

    public void getDocContent(Request request, Response response)
        throws IOException {
      log.entering("SiteAdaptor", "getDocContent",
          new Object[] {request, response});
      String url = request.getDocId().getUniqueId();
      if (getAttachmentDocContent(request, response)) {
        // Success, it was an attachment.
        log.exiting("SiteAdaptor", "getDocContent");
        return;
      }

      Holder<String> listId = new Holder<String>();
      Holder<String> itemId = new Holder<String>();
      // No need to retrieve webId, since it isn't populated when you contact a
      // web's SiteData.asmx page instead of its parent site's.
      boolean result = siteDataClient.getUrlSegments(
          request.getDocId().getUniqueId(), listId, itemId);
      if (!result) {
        // It may still be an aspx page.
        if (request.getDocId().getUniqueId().toLowerCase(Locale.ENGLISH)
            .endsWith(".aspx")) {
          getAspxDocContent(request, response);
        } else {
          log.log(Level.FINE, "responding not found");
          response.respondNotFound();
        }
        log.exiting("SiteAdaptor", "getDocContent");
        return;
      }
      if (itemId.value != null) {
        getListItemDocContent(request, response, listId.value, itemId.value);
      } else if (listId.value != null) {
        getListDocContent(request, response, listId.value);
      } else {
        // Assume it is a top-level site.
        getSiteDocContent(request, response);
      }
      log.exiting("SiteAdaptor", "getDocContent");
    }

    private DocId encodeDocId(String url) {
      log.entering("SiteAdaptor", "encodeDocId", url);
      if (url.toLowerCase().startsWith("https://")
          || url.toLowerCase().startsWith("http://")) {
        // Leave as-is.
      } else if (!url.startsWith("/")) {
        url = webUrl + "/" + url;
      } else {
        // Rip off everthing after the third slash (including the slash).
        // Get http://example.com from http://example.com/some/folder.
        String[] parts = webUrl.split("/", 4);
        url = parts[0] + "//" + parts[2] + url;
      }
      DocId docId = new DocId(url);
      log.exiting("SiteAdaptor", "encodeDocId", docId);
      return docId;
    }

    private URI docIdToUri(DocId docId) throws IOException {
      return spUrlToUri(docId.getUniqueId());
    }

    /**
     * Handles converting from relative paths to fully qualified URIs and
     * dealing with SharePoint's lack of encoding paths (spaces in SP are kept
     * as spaces in URLs, instead of becoming %20).
     */
    private URI sharePointUrlToUri(String path) throws IOException {
      return docIdToUri(encodeDocId(path));
    }

    private void getVirtualServerDocContent(Request request, Response response)
        throws IOException {
      log.entering("SiteAdaptor", "getVirtualServerDocContent",
          new Object[] {request, response});
      VirtualServer vs = siteDataClient.getContentVirtualServer();

      final long necessaryPermissionMask = LIST_ITEM_MASK;
      List<Principal> permits = new ArrayList<Principal>();
      List<Principal> denies = new ArrayList<Principal>();

      // A PolicyUser is either a user or group, but we aren't provided with
      // which. We make a web service call to determine which. When using claims
      // is enabled, we actually do know the type, but we need additional
      // information to produce a clear ACL. As such, we blindly get more info
      // for all the PolicyUsers at once in a single batch.
      Map<String, PrincipalInfo> resolvedPolicyUsers;
      {
        List<String> policyUsers = new ArrayList<String>();
        for (PolicyUser policyUser : vs.getPolicies().getPolicyUser()) {
          policyUsers.add(policyUser.getLoginName());
        }
        resolvedPolicyUsers = resolvePrincipals(policyUsers);
      }

      for (PolicyUser policyUser : vs.getPolicies().getPolicyUser()) {
        String loginName = policyUser.getLoginName();
        PrincipalInfo p = resolvedPolicyUsers.get(loginName);
        if (p == null || !p.isIsResolved()) {
          log.log(Level.WARNING, 
              "Unable to resolve Policy User = {0}", loginName);
          continue;
        }
        // TODO(ejona): special case NT AUTHORITY\LOCAL SERVICE.
        if (p.getPrincipalType() != SPPrincipalType.SECURITY_GROUP
            && p.getPrincipalType() != SPPrincipalType.USER) {
          log.log(Level.WARNING, "Principal {0} is an unexpected type: {1}",
              new Object[] {p.getAccountName(), p.getPrincipalType()});
          continue;
        }
        boolean isGroup
            = p.getPrincipalType() == SPPrincipalType.SECURITY_GROUP;
        String accountName = decodeClaim(p.getAccountName(), p.getDisplayName(),
            isGroup);
        if (accountName == null) {
          log.log(Level.WARNING, 
              "Unable to decode claim. Skipping policy user {0}", loginName);
          continue;
        }
        log.log(Level.FINER, "Policy User accountName = {0}", accountName);
        Principal principal;
        if (isGroup) {
          principal = new GroupPrincipal(accountName, defaultNamespace);
        } else {
          principal = new UserPrincipal(accountName, defaultNamespace);
        }
        long grant = policyUser.getGrantMask().longValue();
        if ((necessaryPermissionMask & grant) == necessaryPermissionMask) {
          permits.add(principal);
        }
        long deny = policyUser.getDenyMask().longValue();
        // If at least one necessary bit is masked, then deny user.
        if ((necessaryPermissionMask & deny) != 0) {
          denies.add(principal);
        }
      }
      response.setAcl(new Acl.Builder()
          .setEverythingCaseInsensitive()
          .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
          .setPermits(permits).setDenies(denies).build());
      
      response.addMetadata(METADATA_OBJECT_TYPE,
          ObjectType.VIRTUAL_SERVER.value());

      HtmlResponseWriter writer = createHtmlResponseWriter(response);
      writer.start(request.getDocId(), ObjectType.VIRTUAL_SERVER,
          vs.getMetadata().getURL());

      writer.startSection(ObjectType.SITE);
      DocIdEncoder encoder = context.getDocIdEncoder();
      for (ContentDatabases.ContentDatabase cdcd
          : vs.getContentDatabases().getContentDatabase()) {
        ContentDatabase cd
            = siteDataClient.getContentContentDatabase(cdcd.getID(), true);
        if (cd.getSites() != null) {
          for (Sites.Site site : cd.getSites().getSite()) {
            writer.addLink(encodeDocId(site.getURL()), null);
          }
        }
      }
      writer.finish();
      log.exiting("SiteAdaptor", "getVirtualServerDocContent");
    }

    /**
     * Returns the url of the parent of the web. The parent url is not the same
     * as the siteUrl, since there may be multiple levels of webs. It is an
     * error to call this method when there is no parent, which is the case iff
     * {@link #isWebSiteCollection} is {@code true}.
     */
    private String getWebParentUrl() {
      if (isWebSiteCollection()) {
        throw new IllegalStateException();
      }
      int slashIndex = webUrl.lastIndexOf("/");
      return webUrl.substring(0, slashIndex);
    }

    /** Returns true if webUrl is a site collection. */
    private boolean isWebSiteCollection() {
      return siteUrl.equals(webUrl);
    }

    /**
     * Returns {@code true} if the current web should not be indexed. This
     * method may issue a request for the web content for all parent webs, so it
     * is expensive, although it uses cached responses to reduce cost.
     */
    private boolean isWebNoIndex(CachedWeb w) throws IOException {
      if ("True".equals(w.noIndex)) {
        return true;
      }
      if (isWebSiteCollection()) {
        return false;
      }
      SiteAdaptor siteAdaptor = getSiteAdaptor(siteUrl, getWebParentUrl());
      return siteAdaptor.isWebNoIndex(
          rareModCache.getWeb(siteAdaptor.siteDataClient));
    }

    private void getSiteDocContent(Request request, Response response)
        throws IOException {
      log.entering("SiteAdaptor", "getSiteDocContent",
          new Object[] {request, response});
      Web w = siteDataClient.getContentWeb();

      if (isWebNoIndex(new CachedWeb(w))) {
        log.fine("Document marked for NoIndex");
        response.respondNotFound();
        log.exiting("SiteAdaptor", "getSiteDocContent");
        return;
      }

      if (webUrl.endsWith("/")) {
        throw new AssertionError();
      }

      if (isWebSiteCollection()) {
        Collection<Principal> admins = new LinkedList<Principal>();
        for (UserDescription user : w.getUsers().getUser()) {
          if (user.getIsSiteAdmin() != TrueFalseType.TRUE) {
            continue;
          }
          Principal principal = userDescriptionToPrincipal(user);
          if (principal == null) {
            log.log(Level.WARNING,
                "Unable to determine login name. Skipping admin user with ID "
                + "{0}", user.getID());
            continue;
          }
          admins.add(principal);
        }
        response.putNamedResource(SITE_COLLECTION_ADMIN_FRAGMENT,
            new Acl.Builder()
              .setEverythingCaseInsensitive()
              .setPermits(admins)
              .setInheritFrom(virtualServerDocId)
              .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
              .build());
      }

      boolean allowAnonymousAccess
          = isAllowAnonymousReadForWeb(new CachedWeb(w))
          // Check if anonymous access is denied by web application policy
          && !isDenyAnonymousAccessOnVirtualServer(
              rareModCache.getVirtualServer());

      if (!allowAnonymousAccess) {
        final boolean includePermissions;
        if (isWebSiteCollection()) {
          includePermissions = true;
        } else {
          SiteAdaptor parentSiteAdaptor
              = getSiteAdaptor(siteUrl, getWebParentUrl());
          Web parentW = parentSiteAdaptor.siteDataClient.getContentWeb();
          String parentScopeId
              = parentW.getMetadata().getScopeID().toLowerCase(Locale.ENGLISH);
          String scopeId
              = w.getMetadata().getScopeID().toLowerCase(Locale.ENGLISH);
          includePermissions = !scopeId.equals(parentScopeId);
        }
        Acl.Builder acl;
        if (includePermissions) {
          List<Permission> permissions
              = w.getACL().getPermissions().getPermission();
          acl = generateAcl(permissions, LIST_ITEM_MASK)
              .setInheritFrom(siteDocId, SITE_COLLECTION_ADMIN_FRAGMENT);
        } else {
          acl = new Acl.Builder().setInheritFrom(new DocId(getWebParentUrl()));
        }
        response.setAcl(acl
            .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
            .build());
      }
      
      response.addMetadata(METADATA_OBJECT_TYPE, ObjectType.SITE.value());
      response.addMetadata(METADATA_PARENT_WEB_TITLE,
          w.getMetadata().getTitle());      

      response.setDisplayUrl(spUrlToUri(w.getMetadata().getURL()));
      HtmlResponseWriter writer = createHtmlResponseWriter(response);
      writer.start(request.getDocId(), ObjectType.SITE,
          w.getMetadata().getTitle());

      DocIdEncoder encoder = context.getDocIdEncoder();
      if (w.getWebs() != null) {
        writer.startSection(ObjectType.SITE);
        for (Webs.Web web : w.getWebs().getWeb()) {
          writer.addLink(encodeDocId(web.getURL()), web.getURL());
        }
      }
      if (w.getLists() != null) {
        writer.startSection(ObjectType.LIST);
        for (Lists.List list : w.getLists().getList()) {
          if ("".equals(list.getDefaultViewUrl())) {
            // Do some I/O to give a good informational message. This is
            // expected to be a very rare case.
            com.microsoft.schemas.sharepoint.soap.List l
                = siteDataClient.getContentList(list.getID());
            log.log(Level.INFO,
                "Ignoring List {0} in {1}, since it has no default view URL",
                new Object[] {l.getMetadata().getTitle(), webUrl});
            continue;
          }
          writer.addLink(encodeDocId(list.getDefaultViewUrl()),
              list.getDefaultViewUrl());
        }
      }
      if (w.getFPFolder() != null) {
        FolderData f = w.getFPFolder();
        if (!f.getFolders().isEmpty()) {
          writer.startSection(ObjectType.FOLDER);
          for (Folders folders : f.getFolders()) {
            if (folders.getFolder() != null) {
              for (Folders.Folder folder : folders.getFolder()) {
                // Lists is always present in the listing but never exists.
                if ("Lists".equals(folder.getURL())) {
                  continue;
                }
                writer.addLink(encodeDocId(folder.getURL()), null);
              }
            }
          }
        }
        if (!f.getFiles().isEmpty()) {
          writer.startSection(ObjectType.LIST_ITEM);
          for (Files files : f.getFiles()) {
            if (files.getFile() != null) {
              for (Files.File file : files.getFile()) {
                writer.addLink(encodeDocId(file.getURL()), null);
              }
            }
          }
        }
      }
      writer.finish();
      log.exiting("SiteAdaptor", "getSiteDocContent");
    }

    private void getListDocContent(Request request, Response response,
        String id) throws IOException {
      log.entering("SiteAdaptor", "getListDocContent",
          new Object[] {request, response, id});
      com.microsoft.schemas.sharepoint.soap.List l
          = siteDataClient.getContentList(id);
      Web w = siteDataClient.getContentWeb();

      if (TrueFalseType.TRUE.equals(l.getMetadata().getNoIndex())
          || isWebNoIndex(new CachedWeb(w))) {
        log.fine("Document marked for NoIndex");
        response.respondNotFound();
        log.exiting("SiteAdaptor", "getListDocContent");
        return;
      }

      boolean allowAnonymousAccess
          = isAllowAnonymousReadForList(new CachedList(l))
          && isAllowAnonymousPeekForWeb(new CachedWeb(w))
          && !isDenyAnonymousAccessOnVirtualServer(
              rareModCache.getVirtualServer());

      if (!allowAnonymousAccess) {
        String scopeId
            = l.getMetadata().getScopeID().toLowerCase(Locale.ENGLISH);
        String webScopeId
            = w.getMetadata().getScopeID().toLowerCase(Locale.ENGLISH);

        DocId rootFolderDocId
            = encodeDocId(l.getMetadata().getRootFolder());

        Acl.Builder acl;
        if (scopeId.equals(webScopeId)) {
          acl = new Acl.Builder().setInheritFrom(new DocId(webUrl));
        } else {
          List<Permission> permissions
              = l.getACL().getPermissions().getPermission();
          acl = generateAcl(permissions, LIST_ITEM_MASK)
              .setInheritFrom(siteDocId, SITE_COLLECTION_ADMIN_FRAGMENT);
        }
        response.setAcl(new Acl.Builder().setInheritFrom(rootFolderDocId)
            .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
            .build());
        context.getAsyncDocIdPusher().pushNamedResource(rootFolderDocId,
                acl.setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
                    .build());
      }

      response.addMetadata(METADATA_OBJECT_TYPE,
          ObjectType.LIST.value());
      response.addMetadata(METADATA_PARENT_WEB_TITLE,
          w.getMetadata().getTitle());
      response.addMetadata(METADATA_LIST_GUID, l.getMetadata().getID());

      response.setDisplayUrl(sharePointUrlToUri(
            "/".equals(l.getMetadata().getDefaultViewUrl()) 
            ? l.getMetadata().getRootFolder() 
            : l.getMetadata().getDefaultViewUrl()));
      String lastModified = l.getMetadata().getLastModified();
      try {
        response.setLastModified(
            listLastModifiedDateFormat.get().parse(lastModified));
      } catch (ParseException ex) {
        log.log(Level.INFO, "Could not parse LastModified: {0}", lastModified);
      }
      HtmlResponseWriter writer = createHtmlResponseWriter(response);
      writer.start(request.getDocId(), ObjectType.LIST,
          l.getMetadata().getTitle());
      processFolder(id, "", writer);
      writer.finish();
      log.exiting("SiteAdaptor", "getListDocContent");
    }

    /**
     * {@code writer} should already have had {@link HtmlResponseWriter#start}
     * called.
     */
    private void processFolder(String listGuid, String folderPath,
        HtmlResponseWriter writer) throws IOException {
      log.entering("SiteAdaptor", "processFolder",
          new Object[] {listGuid, folderPath, writer});
      Paginator<ItemData> folderPaginator
          = siteDataClient.getContentFolderChildren(listGuid, folderPath);
      writer.startSection(ObjectType.LIST_ITEM);
      ItemData folder;
      while ((folder = folderPaginator.next()) != null) {
        Xml xml = folder.getXml();

        Element data = getFirstChildWithName(xml, DATA_ELEMENT);
        for (Element row : getChildrenWithName(data, ROW_ELEMENT)) {
          String rowUrl = row.getAttribute(OWS_SERVERURL_ATTRIBUTE);
          String rowTitle = row.getAttribute(OWS_TITLE_ATTRIBUTE);
          writer.addLink(encodeDocId(rowUrl), rowTitle);
        }
      }
      log.exiting("SiteAdaptor", "processFolder");
    }

    private boolean elementHasName(Element ele, QName name) {
      return name.getLocalPart().equals(ele.getLocalName())
          && name.getNamespaceURI().equals(ele.getNamespaceURI());
    }

    private Element getFirstChildWithName(Xml xml, QName name) {
      for (Object oChild : xml.getAny()) {
        if (!(oChild instanceof Element)) {
          continue;
        }
        Element child = (Element) oChild;
        if (elementHasName(child, name)) {
          return child;
        }
      }
      return null;
    }

    private <T> T getFirstChildOfType(Xml xml, Class<T> type) {
      for (Object oChild : xml.getAny()) {
        if (!type.isInstance(oChild)) {
          continue;
        }
        return type.cast(oChild);
      }
      return null;
    }

    private List<Element> getChildrenWithName(Element ele, QName name) {
      List<Element> l = new ArrayList<Element>();
      NodeList nl = ele.getChildNodes();
      for (int i = 0; i < nl.getLength(); i++) {
        Node n = nl.item(i);
        if (!(n instanceof Element)) {
          continue;
        }
        Element child = (Element) n;
        if (elementHasName(child, name)) {
          l.add(child);
        }
      }
      return l;
    }

    private List<Attr> getAllAttributes(Element ele) {
      NamedNodeMap map = ele.getAttributes();
      List<Attr> attrs = new ArrayList<Attr>(map.getLength());
      for (int i = 0; i < map.getLength(); i++) {
        attrs.add((Attr) map.item(i));
      }
      return attrs;
    }

    private long addMetadata(Response response, String name, String value) {
      return addMetadata(response, name, value, null);
    }

    private long addMetadata(Response response, String name, String value,
        Multimap<String, String> addedMetadata) {
      long size = 0;
      if ("ows_MetaInfo".equals(name)) {
        // ows_MetaInfo is parsed out into other fields for us by SharePoint.
        // We filter it since it only duplicates those other fields.
        return 0;
      }
      if (name.startsWith("ows_")) {
        name = name.substring("ows_".length());
      }
      name = decodeMetadataName(name);
      if (ALTERNATIVE_VALUE_PATTERN.matcher(value).find()) {
        // This is a lookup field. We need to take alternative values only.
        // Ignore the integer part. 314;#pi;#42;#the answer
        String[] parts = value.split(";#", 0);
        for (int i = 1; i < parts.length; i += 2) {
          if (parts[i].isEmpty()) {
            continue;
          }
          response.addMetadata(name, parts[i]);
          if (addedMetadata != null) {
            addedMetadata.put(name, parts[i]);
          }
          // +30 for per-metadata-possible overhead, just to make sure that we
          // don't count too few.
          size += name.length() + parts[i].length() + 30;
        }
      } else if (value.startsWith(";#") && value.endsWith(";#")) {
        // This is a multi-choice field. Values will be in the form:
        // ;#value1;#value2;#
        for (String part : value.split(";#", 0)) {
          if (part.isEmpty()) {
            continue;
          }
          response.addMetadata(name, part);
          if (addedMetadata != null) {
            addedMetadata.put(name, part);
          }
          // +30 for per-metadata-possible overhead, just to make sure that we
          // don't count too few.
          size += name.length() + part.length() + 30;
        }
      } else {
        response.addMetadata(name, value);
        if (addedMetadata != null) {
          addedMetadata.put(name, value);
        }
        // +30 for per-metadata-possible overhead, just to make sure that we
        // don't count too few.
        size += name.length() + value.length() + 30;
      }
      return size;
    }

    private Acl.Builder generateAcl(List<Permission> permissions,
        final long necessaryPermissionMask) throws IOException {
      List<Principal> permits = new LinkedList<Principal>();
      MemberIdMapping mapping = getMemberIdMapping();
      MemberIdMapping newMapping = null;
      for (Permission permission : permissions) {
        // Although it is named "mask", this is really a bit-field of
        // permissions.
        long mask = permission.getMask().longValue();
        if ((necessaryPermissionMask & mask) != necessaryPermissionMask) {
          continue;
        }
        Integer id = permission.getMemberid();
        Principal principal = mapping.getPrincipal(id);
        if (principal == null) {
          if (newMapping == null) {
            newMapping = refreshMemberIdMapping(mapping);
          }
          principal = newMapping.getPrincipal(id);
        }
        if (principal == null) {
          log.log(Level.WARNING, "Could not resolve member id {0}", id);
          continue;
        }
        permits.add(principal);
      }
      return new Acl.Builder().setEverythingCaseInsensitive()
          .setPermits(permits);
    }

    private void addPermitUserToAcl(int userId, Acl.Builder aclToUpdate)
        throws IOException {
      if (userId == -1) {
        return;
      }
      Principal principal = getMemberIdMapping().getPrincipal(userId);
      // MemberIdMapping will have information about users with explicit
      // permissions on SharePoint or users which are direct members of
      // SharePoint groups. MemberIdMapping might not have information
      // about all valid SharePoint Users. To get all valid SharePoint users
      // under SiteCollection, use SiteUserMapping.
      if (principal == null) {
        principal = getSiteUserMapping().getPrincipal(userId);
      }
      if (principal == null) {
        log.log(Level.WARNING, "Could not resolve user id {0}", userId);
        return;
      }

      List<Principal> permits
          = new LinkedList<Principal>(aclToUpdate.build().getPermits());
      permits.add(principal);
      aclToUpdate.setPermits(permits);
    }

    private boolean isPermitted(long permission,
        long necessaryPermission) {
      return (necessaryPermission & permission) == necessaryPermission;
    }

    private boolean isAllowAnonymousPeekForWeb(CachedWeb w) {
      return isPermitted(w.anonymousPermMask, OPEN_MASK);
    }

    private boolean isAllowAnonymousReadForWeb(CachedWeb w) {
      boolean allowAnonymousRead
          = (w.allowAnonymousAccess == TrueFalseType.TRUE)
          && (w.anonymousViewListItems == TrueFalseType.TRUE)
          && isPermitted(w.anonymousPermMask, LIST_ITEM_MASK);
      return allowAnonymousRead;
    }

    private boolean isAllowAnonymousReadForList(CachedList l) {
      boolean allowAnonymousRead
          = (l.readSecurity != LIST_READ_SECURITY_ENABLED)
          && (l.allowAnonymousAccess == TrueFalseType.TRUE)
          && (l.anonymousViewListItems == TrueFalseType.TRUE)
          && isPermitted(l.anonymousPermMask, VIEW_LIST_ITEMS_MASK);
      return allowAnonymousRead;
    }

    private boolean isDenyAnonymousAccessOnVirtualServer(
        CachedVirtualServer vs) {
      if ((LIST_ITEM_MASK & vs.anonymousDenyMask) != 0) {
        return true;
      }
      // Anonymous access is denied if deny read policy is specified for any
      // user or group.
      return vs.policyContainsDeny;
    }

    private void getAspxDocContent(Request request, Response response)
        throws IOException {
      log.entering("SiteAdaptor", "getAspxDocContent",
          new Object[] {request, response});

      CachedWeb w = rareModCache.getWeb(siteDataClient);
      if (isWebNoIndex(w)) {
        log.fine("Document marked for NoIndex");
        response.respondNotFound();
        log.exiting("SiteAdaptor", "getAspxDocContent");
        return;
      }

      String aspxId = request.getDocId().getUniqueId();
      String parentId = aspxId.substring(0, aspxId.lastIndexOf('/'));
      boolean isDirectChild = webUrl.equalsIgnoreCase(parentId);
      // Check for valid ASPX pages
      // Process only direct child for current web
      if (!isDirectChild) {
        // Alternative approach to this string comparison is to make a
        // additional web service call for SiteData.GetContentWeb and
        // check if ASPX page is available under Web.getFPFolder().getFiles()
        log.log(Level.FINE, "Document [{0}] is not a direct child of Web [{1}]",
            new Object[] {aspxId, webUrl});
        response.respondNotFound();
        log.exiting("SiteAdaptor", "getAspxDocContent");
        return;
      }

      boolean allowAnonymousAccess
          = isAllowAnonymousReadForWeb(w)
          // Check if anonymous access is denied by web application policy
          && !isDenyAnonymousAccessOnVirtualServer(
              rareModCache.getVirtualServer());
      if (!allowAnonymousAccess) {
        response.setAcl(new Acl.Builder()
            .setInheritFrom(new DocId(parentId))
            .build());
      }
      response.addMetadata(METADATA_OBJECT_TYPE, "Aspx");      
      response.addMetadata(METADATA_PARENT_WEB_TITLE, w.webTitle);
      getFileDocContent(request, response, true);
      log.exiting("SiteAdaptor", "getAspxDocContent");
    }

    /**
     * Blindly retrieve contents of DocId as if it were a file's URL. To prevent
     * security issues, this should only be used after the DocId has been
     * verified to be a valid document on the SharePoint instance. In addition,
     * ACLs and other metadata and security measures should be set before making
     * this call.
     */
    private void getFileDocContent(Request request, Response response,
        boolean setLastModified) throws IOException {
      log.entering("SiteAdaptor", "getFileDocContent",
          new Object[] {request, response});
      URI displayUrl = docIdToUri(request.getDocId());
      FileInfo fi = httpClient.issueGetRequest(displayUrl.toURL(),
          authenticationHandler.getAuthenticationCookies());
      if (fi == null) {
        response.respondNotFound();
        return;
      }
      try {
        response.setDisplayUrl(displayUrl);
        String contentType = fi.getFirstHeaderWithName("Content-Type");
        if (contentType != null) {
          String lowerType = contentType.toLowerCase(Locale.ENGLISH);
          if (MIME_TYPE_MAPPING.containsKey(lowerType)) {
            contentType = MIME_TYPE_MAPPING.get(lowerType);
          }
          response.setContentType(contentType);
        }
        String lastModifiedString = fi.getFirstHeaderWithName("Last-Modified");
        if (lastModifiedString != null && setLastModified) {
          try {
            response.setLastModified(
                dateFormatRfc1123.get().parse(lastModifiedString));
          } catch (ParseException ex) {
            log.log(Level.INFO, "Could not parse Last-Modified: {0}",
                lastModifiedString);
          }
        }
        IOHelper.copyStream(fi.getContents(), response.getOutputStream());
      } finally {
        fi.getContents().close();
      }
      log.exiting("SiteAdaptor", "getFileDocContent");
    }

    private void getListItemDocContent(Request request, Response response,
        String listId, String itemId) throws IOException {
      log.entering("SiteAdaptor", "getListItemDocContent",
          new Object[] {request, response, listId, itemId});
      CachedList l = rareModCache.getList(siteDataClient, listId);

      CachedWeb w = rareModCache.getWeb(siteDataClient);
      if (TrueFalseType.TRUE.equals(l.noIndex) || isWebNoIndex(w)) {
        log.fine("Document marked for NoIndex");
        response.respondNotFound();
        log.exiting("SiteAdaptor", "getListItemDocContent");
        return;
      }

      boolean applyReadSecurity =
          (l.readSecurity == LIST_READ_SECURITY_ENABLED);
      ItemData i = siteDataClient.getContentItem(listId, itemId);

      Xml xml = i.getXml();
      Element data = getFirstChildWithName(xml, DATA_ELEMENT);
      Element row = getChildrenWithName(data, ROW_ELEMENT).get(0);

      String modifiedString = row.getAttribute(OWS_LAST_MODIFIED_ATTRIBUTE);
      if (modifiedString == null) {
        log.log(Level.FINE, "No last modified information for list item");
      } else {
        // This should be in the form of "1234;#DATE".
        modifiedString = modifiedString.split(";#", 2)[1];
        try {
          response.setLastModified(
              modifiedDateFormat.get().parse(modifiedString));
        } catch (ParseException ex) {
          log.log(Level.INFO, "Could not parse ows_Modified: {0}",
              modifiedString);
        }
      }

      // This should be in the form of "1234;#{GUID}". We want to extract the
      // {GUID}.
      String scopeId
          = row.getAttribute(OWS_SCOPEID_ATTRIBUTE).split(";#", 2)[1];
      scopeId = scopeId.toLowerCase(Locale.ENGLISH);

      // Anonymous access is disabled if read security is applicable for list.
      // Anonymous access for list items is disabled if it does not inherit
      // its effective permissions from list.

      // Even if anonymous access is enabled on list, it can be turned off
      // on Web level by setting Anonymous access to "Nothing" on Web.
      // Anonymous User must have minimum "Open" permission on Web
      // for anonymous access to work on List and List Items.
      boolean allowAnonymousAccess = isAllowAnonymousReadForList(l)
          && scopeId.equals(l.scopeId.toLowerCase(Locale.ENGLISH))
          && isAllowAnonymousPeekForWeb(w)
          && !isDenyAnonymousAccessOnVirtualServer(
              rareModCache.getVirtualServer());

      if (!allowAnonymousAccess) {
      Acl.Builder acl = null;
      if (!applyReadSecurity) {
        String rawFileDirRef = row.getAttribute(OWS_FILEDIRREF_ATTRIBUTE);
        // This should be in the form of "1234;#site/list/path". We want to
        // extract the site/list/path. Path relative to host, even though it
        // doesn't have a leading '/'.
        DocId folderDocId = encodeDocId("/" + rawFileDirRef.split(";#", 2)[1]);
        DocId rootFolderDocId = encodeDocId(l.rootFolder);
        // If the parent is a list, folderDocId will be same as 
        // rootFolderDocId. If inheritance chain is not 
        // broken, item will inherit its permission from list root folder.
        // If parent is a folder, item will inherit its permissions from parent
        // folder.
        boolean parentIsList = folderDocId.equals(rootFolderDocId);      
        String parentScopeId;
        if (parentIsList) {
          com.microsoft.schemas.sharepoint.soap.List list
              = siteDataClient.getContentList(listId);
          parentScopeId
              = list.getMetadata().getScopeID().toLowerCase(Locale.ENGLISH);
        } else {
          // Instead of using getUrlSegments and getContent(ListItem), we could
          // use just getContent(Folder). However, getContent(Folder) always
          // returns children which could make the call very expensive. In
          // addition, getContent(ListItem) returns all the metadata for the
          // folder instead of just its scope so if in the future we need more
          // metadata we will already have it. GetContentEx(Folder) may provide
          // a way to get the folder's scope without its children, but it wasn't
          // investigated.
          Holder<String> folderListId = new Holder<String>();
          Holder<String> folderItemId = new Holder<String>();
          boolean result = siteDataClient.getUrlSegments(
              folderDocId.getUniqueId(), folderListId, folderItemId);
          if (!result) {
            throw new IOException("Could not find parent folder's itemId");
          }
          if (!listId.equals(folderListId.value)) {
            throw new AssertionError("Unexpected listId value");
          }
          ItemData folderItem
              = siteDataClient.getContentItem(listId, folderItemId.value);
          Element folderData = getFirstChildWithName(
              folderItem.getXml(), DATA_ELEMENT);
          Element folderRow
              = getChildrenWithName(folderData, ROW_ELEMENT).get(0);
          parentScopeId = folderRow.getAttribute(OWS_SCOPEID_ATTRIBUTE)
              .split(";#", 2)[1].toLowerCase(Locale.ENGLISH);
        }
        if (scopeId.equals(parentScopeId)) {
          acl = new Acl.Builder().setInheritFrom(folderDocId);
        } else {
          // We have to search for the correct scope within the scopes element.
          // The scope provided in the metadata is for the parent list, not for
          // the item
          Scopes scopes = getFirstChildOfType(xml, Scopes.class);
          for (Scopes.Scope scope : scopes.getScope()) {
            if (scope.getId().toLowerCase(Locale.ENGLISH).equals(scopeId)) {
              acl = generateAcl(scope.getPermission(), LIST_ITEM_MASK)
                  .setInheritFrom(siteDocId, SITE_COLLECTION_ADMIN_FRAGMENT);
              break;
            }
          }
        }

        if (acl == null) {
          throw new IOException("Unable to find permission scope for item: "
              + request.getDocId());
        }
      } else {
        final String fragmentName = "readSecurity";
        List<Permission> permission = null;
        Scopes scopes = getFirstChildOfType(xml, Scopes.class);
        for (Scopes.Scope scope : scopes.getScope()) {
          if (scope.getId().toLowerCase(Locale.ENGLISH).equals(scopeId)) {
            permission = scope.getPermission();
            break;
          }
        }
        if (permission == null) {
          permission
              = i.getMetadata().getScope().getPermissions().getPermission();
        }
        acl = generateAcl(permission, LIST_ITEM_MASK)
            .setInheritFrom(request.getDocId(), fragmentName);
        int authorId = -1;
        String authorValue = row.getAttribute(OWS_AUTHOR_ATTRIBUTE);
        if (authorValue != null) {
          String[] authorInfo = authorValue.split(";#", 2);
          if (authorInfo.length == 2) {
            authorId = Integer.parseInt(authorInfo[0]);
          }
        }
        Acl.Builder aclNamedResource
            = generateAcl(permission, READ_SECURITY_LIST_ITEM_MASK)
            .setInheritFrom(siteDocId, SITE_COLLECTION_ADMIN_FRAGMENT)
            .setInheritanceType(Acl.InheritanceType.AND_BOTH_PERMIT);
        addPermitUserToAcl(authorId, aclNamedResource);
        response.putNamedResource(fragmentName, aclNamedResource.build());
      }
      response.setAcl(acl
          .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
          .build());
      }

      // This should be in the form of "1234;#0". We want to extract the 0.
      String type = row.getAttribute(OWS_FSOBJTYPE_ATTRIBUTE).split(";#", 2)[1];
      boolean isFolder = "1".equals(type);
      String title = row.getAttribute(OWS_TITLE_ATTRIBUTE);
      String serverUrl = row.getAttribute(OWS_SERVERURL_ATTRIBUTE);

      Multimap<String, String> metadata = TreeMultimap.create();
      long metadataLength = 0;
      for (Attr attribute : getAllAttributes(row)) {
        metadataLength += addMetadata(response, attribute.getName(),
            attribute.getValue(), metadata);
      }
      metadataLength += addMetadata(response,
          METADATA_PARENT_WEB_TITLE, w.webTitle);
      metadataLength += addMetadata(response, METADATA_LIST_GUID, listId); 
      
      if (isFolder) {
        String root = encodeDocId(l.rootFolder).getUniqueId();
        root += "/";
        String folder = encodeDocId(serverUrl).getUniqueId();
        if (!folder.startsWith(root)) {
          throw new AssertionError();
        }
        URI displayPage = sharePointUrlToUri(l.defaultViewUrl);
        if (serverUrl.contains("&") || serverUrl.contains("=")
            || serverUrl.contains("%")) {
          throw new AssertionError();
        }
        try {
          // SharePoint percent-encodes '/'s in serverUrl, but accepts them
          // encoded or unencoded. We leave them unencoded for simplicity of
          // implementation and to not deal with the possibility of
          // double-encoding.
          response.setDisplayUrl(new URI(displayPage.getScheme(),
              displayPage.getAuthority(), displayPage.getPath(),
              "RootFolder=" + serverUrl, null));
        } catch (URISyntaxException ex) {
          throw new IOException(ex);
        }
        metadataLength += addMetadata(
            response, METADATA_OBJECT_TYPE, ObjectType.FOLDER.value());
        HtmlResponseWriter writer
            = createHtmlResponseWriter(response, metadataLength);
        writer.start(request.getDocId(), ObjectType.FOLDER, null);
        processAttachments(listId, itemId, row, writer);
        processFolder(listId, folder.substring(root.length()), writer);
        writeMetadataAsContent(writer, metadata);
        writer.finish();
        log.exiting("SiteAdaptor", "getListItemDocContent");
        return;
      }
      String contentTypeId = row.getAttribute(OWS_CONTENTTYPEID_ATTRIBUTE);
      if (contentTypeId != null
          && contentTypeId.startsWith(CONTENTTYPEID_DOCUMENT_PREFIX)) {
        // This is a file (or "Document" in SharePoint-speak), so display its
        // contents.
        metadataLength += addMetadata(
            response, METADATA_OBJECT_TYPE, "Document");
        getFileDocContent(request, response, false);
      } else {
        // Some list item.
        URI displayPage = sharePointUrlToUri(l.defaultViewItemUrl);
        try {
          response.setDisplayUrl(new URI(displayPage.getScheme(),
              displayPage.getAuthority(), displayPage.getPath(),
              "ID=" + itemId, null));
        } catch (URISyntaxException ex) {
          throw new IOException(ex);
        }
        metadataLength += addMetadata(
            response, METADATA_OBJECT_TYPE, ObjectType.LIST_ITEM.value());
        HtmlResponseWriter writer
            = createHtmlResponseWriter(response, metadataLength);
        writer.start(request.getDocId(), ObjectType.LIST_ITEM, title);
        processAttachments(listId, itemId, row, writer);
        writeMetadataAsContent(writer, metadata);
        writer.finish();
      }
      log.exiting("SiteAdaptor", "getListItemDocContent");
    }

    private void processAttachments(String listId, String itemId, Element row,
        HtmlResponseWriter writer) throws IOException {
      String strAttachments = row.getAttribute(OWS_ATTACHMENTS_ATTRIBUTE);
      int attachments = (strAttachments == null || "".equals(strAttachments))
          ? 0 : Integer.parseInt(strAttachments);
      if (attachments > 0) {
        writer.startSection(ObjectType.LIST_ITEM_ATTACHMENTS);
        Item item
            = siteDataClient.getContentListItemAttachments(listId, itemId);
        for (Item.Attachment attachment : item.getAttachment()) {
          writer.addLink(encodeDocId(attachment.getURL()), null);
        }
      }
    }

    /**
     * Write out metadata as content so that snippets can be more helpful.
     */
    private void writeMetadataAsContent(HtmlResponseWriter writer,
        Multimap<String, String> metadata) throws IOException {
      Multimap<String, String> cleanedMetadata = TreeMultimap.create();
      for (Map.Entry<String, String> me : metadata.entries()) {
        String value = me.getValue();
        if (value.startsWith("<") && value.endsWith(">")) {
          // Assume it is HTML and remove the tags, since otherwise the HTML
          // will be encoded and show up in snippets. If we assumed wrong, then
          // we simply removed some content from showing up in snippets. In no
          // way is this cleanup necessary for correctness.
          value = stripHtml(value);
        }
        cleanedMetadata.put(me.getKey(), value);
      }
      writer.addMetadata(cleanedMetadata);
    }

    private boolean getAttachmentDocContent(Request request, Response response)
        throws IOException {
      log.entering("SiteAdaptor", "getAttachmentDocContent", new Object[] {
          request, response});
      String url = request.getDocId().getUniqueId();
      if (!url.contains("/Attachments/")) {
        log.fine("Not an attachment: does not contain /Attachments/");
        log.exiting("SiteAdaptor", "getAttachmentDocContent", false);
        return false;
      }
      String[] parts = url.split("/Attachments/", 2);
      String listBase = parts[0];
      parts = parts[1].split("/", 2);
      if (parts.length != 2) {
        log.fine("Could not separate attachment file name and list item id");
        log.exiting("SiteAdaptor", "getAttachmentDocContent", false);
        return false;
      }
      String itemId = parts[0];
      log.log(Level.FINE, "Detected possible attachment: "
          + "listBase={0}, itemId={1}", new Object[] {listBase, itemId});
      if (!INTEGER_PATTERN.matcher(itemId).matches()) {
        log.fine("Item Id isn't an integer, so it isn't actually an id");
        log.exiting("SiteAdaptor", "getAttachmentDocContent", false);
        return false;
      }
      String listRedirectLocation = httpClient.getRedirectLocation(
          spUrlToUri(listBase).toURL(),
          authenticationHandler.getAuthenticationCookies());
      // if listRedirectLocation is null, use listBase as list url. This is
      // possible if list has no views defined.
      // if listRedirectLocation is not null, it should begin with listBase
      // to be considered as valid list location else use listBase as listUrl. 
      String listUrl 
          = listRedirectLocation == null ? listBase
          : listRedirectLocation.startsWith(listBase) 
          ? listRedirectLocation : listBase;

      log.log(Level.FINER, "List url {0}", listUrl);
      Holder<String> listIdHolder = new Holder<String>();      
      boolean result = siteDataClient.getUrlSegments(listUrl,
          listIdHolder, null);
      // There is a possiblity that default view url for a list is empty but
      // list contains additional non default view.
      // In this case, SharePoint will redirect to non default view url.
      // getUrlSegments call fails for a non default view url.
      // So lets try with listBase for getUrlSegments.
      if (!result && !listUrl.equals(listBase)) {
        result = siteDataClient.getUrlSegments(listBase, listIdHolder, null);
      }
      // For valid lists, one of the getUrlSegments calls above should work on
      // SP2010 and SP2013. It can still fail for SP2007. So lets try with
      // ItemId url. This will fail if parent item is inside a folder.
      if (!result) {
        log.fine("Could not get list id from list url");
        // AllItems.aspx may not be the default view, so hope that list items
        // follow the ${id}_.000-style format and that there aren't any folders.
        result = siteDataClient.getUrlSegments(
            listBase + "/" + itemId + "_.000", listIdHolder, null);
        if (!result) {
          log.fine("Could not get list id from list item url");
          log.exiting("SiteAdaptor", "getAttachmentDocContent", false);
          return false;
        }
      }
      String listId = listIdHolder.value;
      if (listId == null) {
        log.fine("List URL does not point to a list");
        log.exiting("SiteAdaptor", "getAttachmentDocContent", false);
        return false;
      }
      // We have verified that the part before /Attachments/ is a List. Since
      // lists can't have "Attachments" as a child folder, we are very certain
      // that if the document exists it is an attachment.
      log.fine("Suspected attachment verified as being an attachment, assuming "
          + "it exists.");
      CachedList l = rareModCache.getList(siteDataClient, listId);
      CachedWeb w = rareModCache.getWeb(siteDataClient);
      if (TrueFalseType.TRUE.equals(l.noIndex) || isWebNoIndex(w)) {
        log.fine("Document marked for NoIndex");
        response.respondNotFound();
        log.exiting("SiteAdaptor", "getAttachmentDocContent", true);
        return true;
      }
      // TODO(ejona): Figure out a way to give a Not Found if the itemId is
      // wrong. getContentItem() will throw an exception if the itemId does not
      // exist.
      ItemData itemData = siteDataClient.getContentItem(listId, itemId);
      Xml xml = itemData.getXml();
      Element data = getFirstChildWithName(xml, DATA_ELEMENT);
      Element row = getChildrenWithName(data, ROW_ELEMENT).get(0);
      String scopeId
          = row.getAttribute(OWS_SCOPEID_ATTRIBUTE).split(";#", 2)[1];
      scopeId = scopeId.toLowerCase(Locale.ENGLISH);

      String strAttachments = row.getAttribute(OWS_ATTACHMENTS_ATTRIBUTE);
      int attachments = (strAttachments == null || "".equals(strAttachments))
          ? 0 : Integer.parseInt(strAttachments);
      if (attachments <= 0) {
        // Either the attachment has been removed or there was a really odd
        // collection of documents in a Document Library. Therefore, we let the
        // code continue to try to determine if this is a File.
        log.fine("Parent list item has no child attachments");
        log.exiting("SiteAdaptor", "getAttachmentDocContent", false);
        return false;
      }

      boolean allowAnonymousAccess = isAllowAnonymousReadForList(l)
          && scopeId.equals(l.scopeId.toLowerCase(Locale.ENGLISH))
          && isAllowAnonymousPeekForWeb(w)
          && !isDenyAnonymousAccessOnVirtualServer(
              rareModCache.getVirtualServer());
      if (!allowAnonymousAccess) {
        String listItemUrl = row.getAttribute(OWS_SERVERURL_ATTRIBUTE);
        response.setAcl(new Acl.Builder()
            .setInheritFrom(encodeDocId(listItemUrl))
            .build());
      }
      response.addMetadata(METADATA_OBJECT_TYPE, "Attachment");
      response.addMetadata(METADATA_PARENT_WEB_TITLE, w.webTitle);
      response.addMetadata(METADATA_LIST_GUID, listId);
      // If the attachment doesn't exist, then this responds Not Found.
      getFileDocContent(request, response, true);
      log.exiting("SiteAdaptor", "getAttachmentDocContent", true);
      return true;
    }

    private String decodeClaim(String loginName, String name
        , boolean isDomainGroup) {
      if (!loginName.startsWith(IDENTITY_CLAIMS_PREFIX)
          && !loginName.startsWith(OTHER_CLAIMS_PREFIX)) {
        return loginName;
      }
      // AD User
      if (loginName.startsWith("i:0#.w|")) {
        return loginName.substring(7);
      // AD Group
      } else if (loginName.startsWith("c:0+.w|")) {
        return name;
      } else if (loginName.equals("c:0(.s|true")) {
        return "Everyone";
      } else if (loginName.equals("c:0!.s|windows")) {
        return "NT AUTHORITY\\authenticated users";
      // Forms authentication role  
      } else if (loginName.startsWith("c:0-.f|")) {
        return loginName.substring(7).replace("|", ":");
      // Forms authentication user  
      } else if (loginName.startsWith("i:0#.f|")) {
        return loginName.substring(7).replace("|", ":");
      // Identity claims for Email (05) or UPN (0e) for trusted user claim
      } else if (loginName.startsWith("i:05.t|") 
          || loginName.startsWith("i:0e.t|")) {
        String[] parts = loginName.split(Pattern.quote("|"), 3);
        if (parts.length == 3) {
          return parts[2];
        }
      // Non identity claims for email (05) or UPN (0e) or Role (0-)
      } else if (loginName.startsWith("c:05.t|") 
          || loginName.startsWith("c:0e.t|") 
          || loginName.startsWith("c:0-.t|")) {
        String[] parts = loginName.split(Pattern.quote("|"), 3);
        if (parts.length == 3) {
          return parts[2];
        }
      }
      log.log(Level.WARNING, "Unsupported claims value {0}", loginName);
      return null;
    }

    private Map<String, PrincipalInfo> resolvePrincipals(
        List<String> principalsToResolve) {
      Map<String, PrincipalInfo> resolved
          = new HashMap<String, PrincipalInfo>();
      if (principalsToResolve.isEmpty()) {
        return resolved;
      }
      ArrayOfString aos = new ArrayOfString();
      aos.getString().addAll(principalsToResolve);
      ArrayOfPrincipalInfo resolvePrincipals = people.resolvePrincipals(
          aos, SPPrincipalType.ALL, false);
      List<PrincipalInfo> principals = resolvePrincipals.getPrincipalInfo();
      // using loginname from input list principalsToResolve as a key
      // instead of returned PrincipalInfo.getAccountName() as with claims
      // authentication PrincipalInfo.getAccountName() is always encoded.
      // e.g. if login name from Policy is NT Authority\Local Service
      // returned account name is i:0#.w|NT Authority\Local Service
      for (int i = 0; i < principalsToResolve.size(); i++) {
         resolved.put(principalsToResolve.get(i), principals.get(i));
      }
      return resolved;
    }

    private MemberIdMapping retrieveMemberIdMapping() throws IOException {
      log.entering("SiteAdaptor", "retrieveMemberIdMapping");
      Site site = siteDataClient.getContentSite();
      Map<Integer, Principal> map = new HashMap<Integer, Principal>();
      for (GroupMembership.Group group : site.getGroups().getGroup()) {
        map.put(group.getGroup().getID(), new GroupPrincipal(
            group.getGroup().getName(),
            defaultNamespace + "_" + site.getMetadata().getURL()));
      }
      for (UserDescription user : site.getWeb().getUsers().getUser()) {
        Principal principal = userDescriptionToPrincipal(user);
        if (principal == null) {
          log.log(Level.WARNING,
              "Unable to determine login name. Skipping user with ID {0}",
              user.getID());
          continue;
        }
        map.put(user.getID(), principal);
      }
      MemberIdMapping mapping = new MemberIdMapping(map);
      log.exiting("SiteAdaptor", "retrieveMemberIdMapping", mapping);
      return mapping;
    }

    private Map<GroupPrincipal, Collection<Principal>> computeMembersForGroups(
        GroupMembership groups) {
      Map<GroupPrincipal, Collection<Principal>> defs
          = new HashMap<GroupPrincipal, Collection<Principal>>();
      for (GroupMembership.Group group : groups.getGroup()) {
        GroupPrincipal groupPrincipal = new GroupPrincipal(
            group.getGroup().getName(), defaultNamespace + "_" + siteUrl);
        Collection<Principal> members = new LinkedList<Principal>();
        // We always provide membership details, even for empty groups.
        defs.put(groupPrincipal, members);
        if (group.getUsers() == null) {
          continue;
        }
        for (UserDescription user : group.getUsers().getUser()) {
          Principal principal = userDescriptionToPrincipal(user);
          if (principal == null) {
            log.log(Level.WARNING,
                "Unable to determine login name. Skipping user with ID {0}",
                user.getID());
            continue;
          }
          members.add(principal);
        }
      }
      return defs;
    }

    private Principal userDescriptionToPrincipal(UserDescription user) {
      boolean isDomainGroup = (user.getIsDomainGroup() == TrueFalseType.TRUE);
      String userName
          = decodeClaim(user.getLoginName(), user.getName(), isDomainGroup);
      if (userName == null) {
        return null;
      }
      if (isDomainGroup) {
        return new GroupPrincipal(userName, defaultNamespace);
      } else {
        return new UserPrincipal(userName, defaultNamespace);
      }
    }

    private MemberIdMapping retrieveSiteUserMapping()
        throws IOException {
      log.entering("SiteAdaptor", "retrieveSiteUserMapping");
      GetUserCollectionFromSiteResponse.GetUserCollectionFromSiteResult result
          = userGroup.getUserCollectionFromSite();
      Map<Integer, Principal> map = new HashMap<Integer, Principal>();
      MemberIdMapping mapping;
      if (result == null) {
        mapping = new MemberIdMapping(map);
        log.exiting("SiteAdaptor", "retrieveSiteUserMapping", mapping);
        return mapping;
      }
      GetUserCollectionFromSiteResult.GetUserCollectionFromSite siteUsers
           = result.getGetUserCollectionFromSite();
      if (siteUsers.getUsers() == null) {
        mapping = new MemberIdMapping(map);
        log.exiting("SiteAdaptor", "retrieveSiteUserMapping", mapping);
        return mapping;
      }
      for (User user : siteUsers.getUsers().getUser()) {
        boolean isDomainGroup = (user.getIsDomainGroup()
            == com.microsoft.schemas.sharepoint.soap.directory.TrueFalseType.TRUE);
        String userName =
            decodeClaim(user.getLoginName(), user.getName(), isDomainGroup);

        if (userName == null) {
          log.log(Level.WARNING,
              "Unable to determine login name. Skipping user with ID {0}",
              user.getID());
          continue;
        }
        map.put((int) user.getID(),
            new UserPrincipal(userName, defaultNamespace));
      }
      mapping = new MemberIdMapping(map);
      log.exiting("SiteAdaptor", "retrieveSiteUserMapping", mapping);
      return mapping;
    }

    private SiteAdaptor getAdaptorForUrl(String url) throws IOException {
      log.entering("SiteAdaptor", "getAdaptorForUrl", url);
      Holder<String> site = new Holder<String>();
      Holder<String> web = new Holder<String>();
      long result = siteDataClient.getSiteAndWeb(url, site, web);

      if (result != 0) {
        log.exiting("SiteAdaptor", "getAdaptorForUrl", null);
        return null;
      }
      SiteAdaptor siteAdaptor = getSiteAdaptor(site.value, web.value);
      log.exiting("SiteAdaptor", "getAdaptorForUrl", siteAdaptor);
      return siteAdaptor;
    }

    private HtmlResponseWriter createHtmlResponseWriter(Response response)
        throws IOException {
      return createHtmlResponseWriter(response, 0);
    }

    private HtmlResponseWriter createHtmlResponseWriter(
        Response response, long metadataLength) throws IOException {
      response.setContentType("text/html; charset=utf-8");
      // TODO(ejona): Get locale from request.
      return new HtmlResponseWriter(response.getOutputStream(), CHARSET,
          context.getDocIdEncoder(), Locale.ENGLISH,
          maxIndexableSize - metadataLength, context.getDocIdPusher(),
          executor);
    }

    public SiteDataClient getSiteDataClient() {
      return siteDataClient;
    }
  }

  @VisibleForTesting
  static class FileInfo {
    /** Non-null contents. */
    private final InputStream contents;
    /** Non-null headers. Alternates between header name and header value. */
    private final List<String> headers;

    private FileInfo(InputStream contents, List<String> headers) {
      this.contents = contents;
      this.headers = headers;
    }

    public InputStream getContents() {
      return contents;
    }

    public List<String> getHeaders() {
      return headers;
    }

    public int getHeaderCount() {
      return headers.size() / 2;
    }

    public String getHeaderName(int i) {
      return headers.get(2 * i);
    }

    public String getHeaderValue(int i) {
      return headers.get(2 * i + 1);
    }

    /**
     * Find the first header with {@code name}, ignoring case.
     */
    public String getFirstHeaderWithName(String name) {
      String nameLowerCase = name.toLowerCase(Locale.ENGLISH);
      for (int i = 0; i < getHeaderCount(); i++) {
        String headerNameLowerCase
            = getHeaderName(i).toLowerCase(Locale.ENGLISH);
        if (headerNameLowerCase.equals(nameLowerCase)) {
          return getHeaderValue(i);
        }
      }
      return null;
    }

    public static class Builder {
      private InputStream contents;
      private List<String> headers = Collections.emptyList();

      public Builder(InputStream contents) {
        setContents(contents);
      }

      public Builder setContents(InputStream contents) {
        if (contents == null) {
          throw new NullPointerException();
        }
        this.contents = contents;
        return this;
      }

      /**
       * Sets the headers recieved as a response. List must alternate between
       * header name and header value.
       */
      public Builder setHeaders(List<String> headers) {
        if (headers == null) {
          throw new NullPointerException();
        }
        if (headers.size() % 2 != 0) {
          throw new IllegalArgumentException(
              "headers must have an even number of elements");
        }
        this.headers = Collections.unmodifiableList(
            new ArrayList<String>(headers));
        return this;
      }

      public FileInfo build() {
        return new FileInfo(contents, headers);
      }
    }
  }

  @VisibleForTesting
  interface HttpClient {
    /**
     * The caller must call {@code fileInfo.getContents().close()} after use.
     *
     * @return {@code null} if not found, {@code FileInfo} instance otherwise
     */
    public FileInfo issueGetRequest(URL url, List<String> authenticationCookies)
        throws IOException;
    
    public String getRedirectLocation(URL url,
        List<String> authenticationCookies) throws IOException;
  }

  static class HttpClientImpl implements HttpClient {
    @Override
    public FileInfo issueGetRequest(URL url, List<String> authenticationCookies)
        throws IOException {
      // Handle Unicode. Java does not properly encode the GET.
      try {
        url = new URL(url.toURI().toASCIIString());
      } catch (URISyntaxException ex) {
        throw new IOException(ex);
      }
      HttpURLConnection conn = (HttpURLConnection) url.openConnection();
      // TODO :Close connection for non 200 responses.
      if (authenticationCookies.isEmpty()) {
        conn.addRequestProperty("X-FORMS_BASED_AUTH_ACCEPTED", "f");
      } else {
        for (String cookie : authenticationCookies) {
          conn.addRequestProperty("Cookie", cookie);
        }
      }
      conn.setDoInput(true);
      conn.setDoOutput(false);
      if (conn.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
        return null;
      }
      if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
        throw new IOException("Got status code: " + conn.getResponseCode());
      }
      String errorHeader = conn.getHeaderField("SharePointError");
      // SharePoint adds header SharePointError to response to indicate error
      // on SharePoint for requested URL.
      // errorHeader = 2 if SharePoint rejects current request because 
      // of current processing load
      // errorHeader = 0 for other errors on SharePoint server
      
      if (errorHeader != null) {            
        if ("2".equals(errorHeader)) {
          throw new IOException("Got error 2 from SharePoint for URL [" + url 
              + "]. Error Code 2 indicates SharePoint has rejected current "
              + "request because of current processing load on SharePoint.");            
        } else {
          throw new IOException("Got error " + errorHeader 
              + " from SharePoint for URL [" + url + "].");
        }
      }
      
      List<String> headers = new LinkedList<String>();
      // Start at 1 since index 0 is special.
      for (int i = 1;; i++) {
        String key = conn.getHeaderFieldKey(i);
        if (key == null) {
          break;
        }
        String value = conn.getHeaderField(i);
        headers.add(key);
        headers.add(value);
      }
      log.log(Level.FINER, "Response HTTP headers: {0}", headers);
      return new FileInfo.Builder(conn.getInputStream()).setHeaders(headers)
          .build();
    }

    @Override
    public String getRedirectLocation(URL url,
        List<String> authenticationCookies) throws IOException {

      // Handle Unicode. Java does not properly encode the GET.
      try {
        url = new URL(url.toURI().toASCIIString());
      } catch (URISyntaxException ex) {
        throw new IOException(ex);
      }
      HttpURLConnection conn = (HttpURLConnection) url.openConnection();
      try {
        if (authenticationCookies.isEmpty()) {
          conn.addRequestProperty("X-FORMS_BASED_AUTH_ACCEPTED", "f");
        } else {
          for (String cookie : authenticationCookies) {
            conn.addRequestProperty("Cookie", cookie);
          }
        }
        conn.setDoInput(true);
        conn.setDoOutput(false);
        conn.setInstanceFollowRedirects(false);       
        if (conn.getResponseCode() != HttpURLConnection.HTTP_MOVED_TEMP) {
          log.log(Level.WARNING,
              "Received response code {0} instead of 302 for URL {1}",
              new Object[]{conn.getResponseCode(), url});
          return null;        
        }
        return conn.getHeaderField("Location");
      } finally {
        InputStream inputStream = conn.getResponseCode() >= 400
            ? conn.getErrorStream() : conn.getInputStream();
        inputStream.close();
      }
    }
  }

  @VisibleForTesting
  interface SoapFactory {
    /**
     * The {@code endpoint} string is a SharePoint URL, meaning that spaces are
     * not encoded.
     */
    public SiteDataSoap newSiteData(String endpoint);

    public UserGroupSoap newUserGroup(String endpoint);
    
    public PeopleSoap newPeople(String endpoint);
  }

  @VisibleForTesting
  static class SoapFactoryImpl implements SoapFactory {
    private final Service siteDataService;
    private final Service userGroupService;
    private final Service peopleService;

    public SoapFactoryImpl() {
      this.siteDataService = SiteDataClient.createSiteDataService();
      this.userGroupService = Service.create(
          UserGroupSoap.class.getResource("UserGroup.wsdl"),
          new QName(XMLNS_DIRECTORY, "UserGroup"));
      this.peopleService = Service.create(
          PeopleSoap.class.getResource("People.wsdl"),
          new QName(XMLNS, "People"));
    }

    private static String handleEncoding(String endpoint) {
      // Handle Unicode. Java does not properly encode the POST path.
      return URI.create(endpoint).toASCIIString();
    }

    @Override
    public SiteDataSoap newSiteData(String endpoint) {
      EndpointReference endpointRef = new W3CEndpointReferenceBuilder()
          .address(handleEncoding(endpoint)).build();
      return siteDataService.getPort(endpointRef, SiteDataSoap.class);
    }

    @Override
    public UserGroupSoap newUserGroup(String endpoint) {
      EndpointReference endpointRef = new W3CEndpointReferenceBuilder()
          .address(handleEncoding(endpoint)).build();
      return userGroupService.getPort(endpointRef, UserGroupSoap.class);
    }

    @Override
    public PeopleSoap newPeople(String endpoint) {
      EndpointReference endpointRef = new W3CEndpointReferenceBuilder()
          .address(handleEncoding(endpoint)).build();
      return peopleService.getPort(endpointRef, PeopleSoap.class);      
    }
  }

  private static class NtlmAuthenticator extends Authenticator {
    private final String username;
    private final char[] password;
    private final Set<String> permittedHosts = new HashSet<String>();

    public NtlmAuthenticator(String username, String password) {
      this.username = username;
      this.password = password.toCharArray();
    }

    public void addPermitForHost(URL urlContainingHost) {
      permittedHosts.add(urlToHostString(urlContainingHost));
    }
    
    private boolean isPermittedHost(URL toVerify) {
      return permittedHosts.contains(urlToHostString(toVerify));
    }
    

    private String urlToHostString(URL url) {
      // If the port is missing (so that the default is used), we replace it
      // with the default port for the protocol in order to prevent being able
      // to prevent being tricked into connecting to a different port (consider
      // being configured for https, but then getting tricked to use http and
      // evenything being in the clear).
      return "" + url.getHost()
          + ":" + (url.getPort() != -1 ? url.getPort() : url.getDefaultPort());
    }

    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
      URL url = getRequestingURL();
      if (isPermittedHost(url)) {
        return new PasswordAuthentication(username, password);
      } else {
        return super.getPasswordAuthentication();
      }
    }
  }

  private class MemberIdMappingCallable implements Callable<MemberIdMapping> {
    private final String siteUrl;

    public MemberIdMappingCallable(String siteUrl) {
      if (siteUrl == null) {
        throw new NullPointerException();
      }
      this.siteUrl = siteUrl;
    }

    @Override
    public MemberIdMapping call() throws Exception {
      try {
        return memberIdsCache.get(siteUrl);
      } catch (ExecutionException ex) {
        Throwable cause = ex.getCause();
        if (cause instanceof Exception) {
          throw (Exception) cause;
        } else if (cause instanceof Error) {
          throw (Error) cause;
        } else {
          throw new AssertionError(cause);
        }
      }
    }
  }

  @VisibleForTesting
  class SiteUserIdMappingCallable implements Callable<MemberIdMapping> {
    private final String siteUrl;

    public SiteUserIdMappingCallable(String siteUrl) {
      if (siteUrl == null) {
        throw new NullPointerException();
      }
      this.siteUrl = siteUrl;
    }

    @Override
    public MemberIdMapping call() throws Exception {
      try {
        return siteUserCache.get(siteUrl);
      } catch (ExecutionException ex) {
        Throwable cause = ex.getCause();
        if (cause instanceof Exception) {
          throw (Exception) cause;
        } else if (cause instanceof Error) {
          throw (Error) cause;
        } else {
          throw new AssertionError(cause);
        }
      }
    }
  }

  private class MemberIdsCacheLoader
      extends AsyncCacheLoader<String, MemberIdMapping> {
    @Override
    protected Executor executor() {
      return executor;
    }

    @Override
    public MemberIdMapping load(String site) throws IOException {
      return getSiteAdaptor(site, site).retrieveMemberIdMapping();
    }
  }

  private class SiteUserCacheLoader
      extends AsyncCacheLoader<String, MemberIdMapping> {
    @Override
    protected Executor executor() {
      return executor;
    }

    @Override
    public MemberIdMapping load(String site) throws IOException {
      return getSiteAdaptor(site, site).retrieveSiteUserMapping();
    }
  }

  private static class CachedThreadPoolFactory
      implements Callable<ExecutorService> {
    @Override
    public ExecutorService call() {
      return Executors.newCachedThreadPool();
    }
  }
}
