Merge branch 'master' of https://code.google.com/p/plexi
diff --git a/build.xml b/build.xml
index 95b058c..9b4046c 100644
--- a/build.xml
+++ b/build.xml
@@ -76,13 +76,11 @@
     <fileset dir="${lib.dir}">
       <!--include name="guice-3.0.jar"/-->
       <include name="jsr305.jar"/>
-      <include name="servlet-api.jar"/>
 
       <!-- Dependencies that are in common with opensaml. -->
       <include name="joda-time-1.6.jar"/>
       <include name="opensaml-2.3.2.jar"/>
       <include name="openws-1.3.1.jar"/>
-      <include name="slf4j-api-1.5.10.jar"/>
       <include name="xmltooling-1.2.2.jar"/>
     </fileset>
   </path>
diff --git a/lib/servlet-api.jar b/lib/servlet-api.jar
deleted file mode 100644
index e76311f..0000000
--- a/lib/servlet-api.jar
+++ /dev/null
Binary files differ
diff --git a/src/com/google/common/base/Pair.java b/src/com/google/common/base/Pair.java
deleted file mode 100644
index 11b94cb..0000000
--- a/src/com/google/common/base/Pair.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Copyright (c) 2008 Google Inc.
- *
- * 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.common.base;
-
-import java.io.Serializable;
-/**
- * Pair is an expedient way to combine two arbitrary objects into one.  <b>Its
- * use is not to be preferred</b> to creating a custom type, but it can be
- * handy in a pinch.  If your {@link #equals}, {@link #hashCode},
- * {@link #toString}, and/or {@link #clone} behavior matter to you at all, you
- * may not want to use this (or you may at least wish to subclass).
- *
- *
-
- *
- * <p>This class may be used with the Google Web Toolkit (GWT).
- *
- */
-public class Pair<A,B> implements Serializable, Cloneable {
-  private static final long serialVersionUID = 747826592375603043L;
-
-  /** Creates a new pair containing the given objects in order. */
-  public static <A,B> Pair<A,B> of(A first, B second) {
-    return new Pair<A,B>(first, second);
-  }
-
-  /** The first element of the pair. */
-  public final A first;
-
-  /** The second element of the pair. */
-  public final B second;
-
-  /** Cumbersome way to create a new pair (see {@link #of}. */
-  public Pair(A first, B second) {
-    this.first = first;
-    this.second = second;
-  }
-
-  /** Optional accessor method for {@link #first}. */
-  public A getFirst() {
-    return first;
-  }
-
-  /** Optional accessor method for {@link #second}. */
-  public B getSecond() {
-    return second;
-  }
-
-  @Override public Pair<A,B> clone() {
-    try {
-      @SuppressWarnings("unchecked")
-      Pair<A,B> result = (Pair<A,B>) super.clone();
-      return result;
-    } catch (CloneNotSupportedException e) {
-      throw new AssertionError(e);
-
-
-
-
-
-    }
-  }
-
-  @Override public boolean equals(Object object) {
-
-
-    if (object instanceof Pair<?,?>) {
-      Pair<?,?> other = (Pair<?,?>) object;
-      return eq(first, other.first) && eq(second, other.second);
-    }
-    return false;
-  }
-
-  @Override public int hashCode() {
-    /*
-     * This combination yields entropy comparable to constituent hashes
-     * and ensures that hash(a,b) != hash(b,a).
-     */
-    return (hash(first, 0) + 0xDeadBeef) ^ hash(second, 0);
-  }
-
-  /**
-   * This implementation returns the String representation of this pair in
-   * the form {@code (string1, string2)}, where {@code string1} and
-   * {@code string2} are the {@link Object#toString} representations of the
-   * elements inside the pair.
-   */
-  @Override public String toString() {
-    return String.format("(%s, %s)", first, second);
-  }
-
-
-  private static boolean eq(Object a, Object b) {
-    return a == b || (a != null && a.equals(b));
-  }
-
-  private static int hash(Object object, int nullHash) {
-    return (object == null) ? nullHash : object.hashCode();
-  }
-}
diff --git a/src/com/google/common/labs/matcher/ParsedUrlPattern.java b/src/com/google/common/labs/matcher/ParsedUrlPattern.java
deleted file mode 100644
index 31812c9..0000000
--- a/src/com/google/common/labs/matcher/ParsedUrlPattern.java
+++ /dev/null
@@ -1,621 +0,0 @@
-// Copyright 2008 Google Inc.
-//
-// 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.common.labs.matcher;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import com.google.common.base.Preconditions;
-
-/**
- * This class parses a Google URL pattern into an immutable representation that
- * provides equivalent Java regexes,
- * exact-match patterns and prefix patterns, as appropriate. For a description
- * of Google URL patterns, see the
- * documentation in <a
- * href="http://code.google.com/apis/searchappliance/documentation/50/admin/URL_patterns.html">
- * this document</a>.
- * <p>
- * All Google URL patterns can be translated into an equivalent Java regex (with
- * some exceptions and caveats, see below). This class provides access to an
- * equivalent Java regex through {@link #getUrlRegex()}.
- * <p>
- * In addition, the class provides further analysis and special kinds of
- * patterns, depending on these top-level predicates:
- * <ul>
- * <li> {@link #isHostPathType()}: Returns {@code true} if the parsed pattern
- * is a "host-path" pattern. A "host-path" pattern is a pattern that can be
- * parsed into two regexes, a host regex and a path regex, such that a subject
- * URL matches the original URL pattern iff the host portion matches the host
- * regex and the path portion matches the path regex. If
- * {@code isHostPathType()} is true, then {@link #getHostRegex()} and
- * {@link #getPathRegex()} return the corresponding regexes. </li>
- * <li> {@link #isPathPrefixMatch()}: Returns {@code true} if the parsed
- * pattern is a "host-path" pattern and the path portion of the pattern is
- * simply a fixed string that must appear at the beginning of the path. In this
- * case, {@link #getPathPrefixString()} returns a simple string (not a regex)
- * that can be matched against the start of the subject URL's path. </li>
- * <li> {@link #isPathExactMatch()}: Returns {@code true} if if the parsed
- * pattern is a "host-path" pattern and the path portion of the pattern is an
- * exact-match string. In this case, {@link #getPathExactString()} returns a
- * simple string (not a regex) that can be matched exactly against the subject
- * URL's path. </li>
- * </ul>
- * In summary:
- * <ul>
- * <li> {@code getUrlRegex()} provides an equivalent Java regex for the entire
- * pattern. </li>
- * <li> If {@code isHostPathType()} is true, then, {@code getHostRegex()} and
- * {@code getPathRegex()} return regexes for the two portions.</li>
- * <li> If {@code isPrefixPathMatch()} is true, then,
- * {@code getPrefixPathMatchPattern()} returns a simple string pattern for
- * prefix match.</li>
- * <li> If {@code isPathExactMatch()} is true, then, in addition,
- * {@code getPathExactMatchPattern()} returns a simple string pattern for exact
- * match.
- * </ul>
- * <p>
- * Note: the "path" portion is the hierarchical part, that is, everything
- * following the first slash (not the {@code ://}). The "host" portion is
- * everything before that. For example: for the URL
- * {@code http://www.example.com/foo/bar}, the protocol-authority portion is
- * {@code http://www.example.com/} and the file portion is {@code /foo/bar}.
- * Note the the middle slash appears in both portions.
- * <p>
- * A parser is provided to separate a URL string into host and path portions:
- * {@link AnalyzedUrl}. You can access the host and path portions through
- * {@link AnalyzedUrl#getHostPart()} and {@link AnalyzedUrl#getPathPart()}. It
- * is recommended that this parser be used rather than the standard
- * {@code getHost()} and {@code getPath()} functions of {@link java.net.URL},
- * because this class and {@code AnalyzedUrl} share parsing infrastructure and
- * at present, there is at least one significant difference:
- * {@code AnalyzedUrl.getPathPart()} includes the leading slash but
- * {@code java.net.URL.getPath()} does not. TODO: fix this.
- * <p>
- * Exceptions and caveats: not all forms of Google URL patterns are currently
- * supported. At present, these exceptions and special cases apply:
- * <ul>
- * <li> {@code www?:} patterns are not supported </li>
- * <li> {@code regexp:} and {@code regexpCase:} patterns are translated simply
- * by removing those two prefixes. Thus, the remaining pattern is assumed to be
- * a Java regex, not a GNU regex (as documented on the <a
- * href="http://code.google.com/apis/searchappliance/documentation/50/admin/URL_patterns.html">
- * reference site</a>). </li>
- * <li> {@code regexpIgnoreCase:} patterns are handled similarly. In this case,
- * the prefix is removed and the pattern is enclosed in {@code (?i:}...{@code )}</li>
- * <li> Exception patterns (patterns with leading {@code -} or {@code +-}) are
- * not supported.</li>
- * </ul>
- */
-public class ParsedUrlPattern {
-
-  private final String urlPattern;
-  private final String urlRegex;
-
-  private final boolean hostPathType;
-  private final String hostRegex;
-
-  private final String pathRegex;
-  private final boolean pathExactMatch;
-  private final String pathExactMatchPattern;
-
-  private final boolean prefixPathMatch;
-  private final String prefixPathMatchPattern;
-
-  /**
-   * Parses a Google URL pattern to Java regexes. Google URL patterns are
-   * publicly documented <a
-   * href="http://code.google.com/apis/searchappliance/documentation/50/admin/URL_patterns.html">
-   * here </a>.
-   * 
-   * @param urlPattern A Google URL pattern
-   * @throws IllegalArgumentException if the URL pattern is unsupported or can
-   *         not be parsed
-   */
-  public ParsedUrlPattern(String urlPattern) {
-    ParsedUrlPatternBuilder t = new ParsedUrlPatternBuilder(urlPattern);
-    this.urlPattern = t.urlPattern;
-    this.urlRegex = t.urlRegex;
-    this.hostPathType = t.hostPathType;
-    this.hostRegex = t.hostRegex;
-    this.pathRegex = t.pathRegex;
-    this.pathExactMatch = t.pathExactMatch;
-    this.pathExactMatchPattern = t.pathExactMatchPattern;
-    this.prefixPathMatch = t.prefixPathMatch;
-    this.prefixPathMatchPattern = t.prefixPathMatchPattern;
-
-  }
-
-  /**
-   * Returns a regex that matches the entire URL. A subject string matches the
-   * URL pattern iff it matches this regex.
-   * 
-   * @return a regex that matches the entire URL
-   */
-  public String getUrlRegex() {
-    return urlRegex;
-  }
-
-  /**
-   * Returns {@code true} if the parsed pattern is a "host-path" pattern. A
-   * "host-path" pattern is a pattern that can be parsed into two regexes, a
-   * host regex and a path regex, such that a subject url matches the pattern
-   * iff the host portion matches the host regex and the path portion matches
-   * the path regex.
-   * <p>
-   * For example, the pattern {@code example.com/foo} might be parsed into two
-   * regexes, host regex: {@code example.com/$} and path regex: {@code ^/foo}.
-   */
-  public boolean isHostPathType() {
-    return hostPathType;
-  }
-
-  /**
-   * Returns a regex that matches the host (protocol and authority) portion of
-   * the URL. If this is a host-path regex then a subject string matches the url
-   * pattern iff the host portion matches this regex and the the path portion
-   * matches the corresponding path regex (obtained by {@link #getPathRegex()}).
-   * <p>
-   * This should be used against URLs that have been parsed using the
-   * {@link AnalyzedUrl} class.
-   * <p>
-   * Note: this should only be used if {@code isHostPathType()} is true; if not,
-   * then this method throws an {@code IllegalStateException}.
-   * 
-   * @return a regex that matches the host (protocol and authority) portion of
-   *         the URL
-   * @throws IllegalStateException if {@code isHostPathType()} is false
-   */
-  public String getHostRegex() {
-    Preconditions.checkState(isHostPathType());
-    return hostRegex;
-  }
-
-  /**
-   * Returns a regex that matches the path (hierarchical) portion of the URL.
-   * <p>
-   * This should be used against URLs that have been parsed using the
-   * {@link AnalyzedUrl} class.
-   * <p>
-   * Note: this should only be used if {@link #isHostPathType()} is true; if
-   * not, then this method throws an {@code IllegalStateException}.
-   * 
-   * @return a regex that matches the path (hierarchical) portion of the URL
-   * @throws IllegalStateException if {@code isHostPathType()} is false
-   */
-  public String getPathRegex() {
-    Preconditions.checkState(isHostPathType());
-    return pathRegex;
-  }
-
-  /**
-   * Indicates whether the parsed pattern gives a prefix match pattern. If this
-   * is true, then this pattern can be obtained using
-   * {@link #getPathPrefixString()}.
-   * 
-   * @return {@code true} if the parsed pattern gives an prefix match pattern.
-   */
-  public boolean isPathPrefixMatch() {
-    return prefixPathMatch;
-  }
-
-  /**
-   * If {@link #isPathPrefixMatch()} is true, then this returns a simple string
-   * that can be matched against the path portion of a subject string using
-   * {@link String#startsWith(String)}.
-   * <p>
-   * Note: this should only be used if {@code isPrefixPathMatch()} is true; if
-   * not, then this method throws an {@code IllegalStateException}.
-   * 
-   * @return a string that matches a prefix of the path portion of the URL
-   * @throws IllegalStateException if {@code isPathPrefixMatch()} is false
-   */
-  public String getPathPrefixString() {
-    Preconditions.checkState(isPathPrefixMatch());
-    return prefixPathMatchPattern;
-  }
-
-  /**
-   * Returns whether the parsed pattern gives an exact match pattern. If this is
-   * true, then this pattern can be obtained using {@link #getPathExactString()}.
-   * 
-   * @return {@code true} if the parsed pattern gives an exact match pattern.
-   */
-  public boolean isPathExactMatch() {
-    return pathExactMatch;
-  }
-
-  /**
-   * If {@link #isPathExactMatch()} is true, then this returns a simple string
-   * that can be matched against the path portion of a subject string using
-   * {@link String#equals(Object)}. Note: this should only be used if
-   * {@code isPathExactMatch()} is true; if not, then this method throws an
-   * {@code IllegalStateException}.
-   * 
-   * @return a string that matches the entire path
-   * @throws IllegalStateException if {@code isPathExactMatch()} is false
-   */
-  public String getPathExactString() {
-    Preconditions.checkState(isPathExactMatch());
-    return pathExactMatchPattern;
-  }
-
-  /**
-   * Returns the original URL pattern.
-   * 
-   * @return the original URL pattern.
-   */
-  public String getUrlPattern() {
-    return urlPattern;
-  }
-
-  // This is the master meta-regex. This is used both for parsing URL patterns
-  // and for parsing URLs
-  private static final String URL_METAPATTERN_STRING =
-      "\\A(\\^)?((?:([^/:$<]*)((?:(?::|(?::/))?\\Z)|(?:://)))?" +
-    // ___1_____2a__3_________4b__c____d____________e
-      "(?:([^/:@]*)@)?([^/:<]*)?(?::([^/<]*))?)(/|(?:</>))?(?:(.*?)(\\Z|\\$)?)?\\Z"
-    // f__5___________6_________g___7__________8__h________i__9____0
-  ;
-
-  // Groups: (capturing groups are numbered, non-capturing are lettered)
-  // 1 anchor (^)
-  // 2 protocol + authority (not including /)
-  // a protocol + ((nothing or : or :/ followed by end of pattern) or ::/)
-  // 3 protocol
-  // 4 protocol separator ((nothing or : or :/ followed by end of pattern) or
-  // ::/)
-  // b nothing or : or :/ followed by end of pattern
-  // c : or :/
-  // d :/
-  // e ::/
-  // f userinfo + @
-  // 5 userinfo
-  // 6 host
-  // g : + port
-  // 7 port
-  // 8 slash (after authority) (could be a slash or "</>")
-  // h </>
-  // i file + anchor
-  // 9 file
-  // 10 anchor ($)
-  
-  // This Pattern is package visible so it can be used by AnalyzedUrl
-  static final Pattern URL_METAPATTERN = Pattern.compile(URL_METAPATTERN_STRING);
-
-  // As above, the enum is package visible so it can be used by AnalyzedUrl
-  // Note: if you change the master regex, you should change this enum to match
-  static enum MetaRegexGroup {
-    LEFT_ANCHOR(1), PROTOCOL_AUTHORITY(2), PROTOCOL(3), PROTOCOL_SEPARATOR(4), USERINFO(5),
-    HOST(6), PORT(7), SLASH_AFTER_AUTHORITY(8), FILE(9), RIGHT_ANCHOR(10);
-    private int n;
-
-    MetaRegexGroup(int n) {
-      this.n = n;
-    }
-
-    int intValue() {
-      return n;
-    }
-  }
-
-  // This static helper is also shared with the AnalyzedUrl
-  static String getGroup(Matcher m, MetaRegexGroup g) {
-    String s = m.group(g.intValue());
-    return (s == null) ? "" : s;
-  }
-
-  private static class ParsedUrlPatternBuilder {
-
-    public String urlPattern;
-    public String urlRegex;
-
-    public boolean hostPathType;
-    public String hostRegex;
-
-    public String pathRegex;
-    public boolean pathExactMatch;
-    public String pathExactMatchPattern;
-
-    public boolean prefixPathMatch;
-    public String prefixPathMatchPattern;
-
-    ParsedUrlPatternBuilder(String urlPattern) {
-      checkPatternValidity(urlPattern);
-      this.urlPattern = urlPattern;
-      analyze();
-    }
-
-    private void analyze() {
-      if (urlPattern.startsWith(CONTAINS_PATTERNS_METAPATTERN_PREFIX)) {
-        urlRegex =
-            Pattern.quote(urlPattern.substring(CONTAINS_PATTERNS_METAPATTERN_PREFIX.length()));
-        initNonHostPathPattern();
-        return;
-      }
-
-      if (urlPattern.startsWith(REGEXP_PATTERNS_METAPATTERN_PREFIX)) {
-        urlRegex = urlPattern.substring(REGEXP_PATTERNS_METAPATTERN_PREFIX.length());
-        initNonHostPathPattern();
-        return;
-      }
-
-      if (urlPattern.startsWith(REGEXPCASE_PATTERNS_METAPATTERN_PREFIX)) {
-        urlRegex = urlPattern.substring(REGEXPCASE_PATTERNS_METAPATTERN_PREFIX.length());
-        initNonHostPathPattern();
-        return;
-      }
-
-      if (urlPattern.startsWith(REGEXPIGNORECASE_PATTERNS_METAPATTERN_PREFIX)) {
-        urlRegex =
-            "(?i:" + urlPattern.substring(REGEXPIGNORECASE_PATTERNS_METAPATTERN_PREFIX.length())
-                + ")";
-        initNonHostPathPattern();
-        return;
-      }
-
-      initHostPathPattern();
-
-      if (isNullOrEmpty(urlPattern)) {
-        prefixPathMatch = true;
-        return;
-      }
-      if (testForAndHandleNoSlashSuffixPattern()) {
-        return;
-      }
-      Matcher m = URL_METAPATTERN.matcher(urlPattern);
-      Preconditions.checkArgument(m.find(), "problem parsing urlpattern: " + urlPattern);
-      urlRegex = buildUrlRegex(m);
-      pathRegex = buildPathRegex(m);
-      hostRegex = buildHostRegex(m);
-    }
-
-    private void initNonHostPathPattern() {
-      hostPathType = false;
-      pathRegex = null;
-      hostRegex = null;
-      pathExactMatch = false;
-      pathExactMatchPattern = null;
-      prefixPathMatch = false;
-      prefixPathMatchPattern = null;
-    }
-
-    private void initHostPathPattern() {
-      hostPathType = true;
-      urlRegex = "";
-      pathRegex = "";
-      hostRegex = "";
-      pathExactMatch = false;
-      pathExactMatchPattern = null;
-      prefixPathMatch = false;
-      prefixPathMatchPattern = "/";
-    }
-
-    // A suffix pattern (ends in $) that has no slash just doesn't parse well
-    // with
-    // the metapattern. So we use a special pattern for this case.
-    private boolean testForAndHandleNoSlashSuffixPattern() {
-      Matcher m = NO_SLASH_SUFFIX_PATTERN.matcher(urlPattern);
-      if (!m.find()) {
-        return false;
-      }
-      urlRegex = Pattern.quote(m.group(1)) + OUTPUT_RIGHT_ANCHOR_PATTERN_STRING;
-      pathRegex = urlRegex;
-      hostRegex = "";
-      pathExactMatch = false;
-      pathExactMatchPattern = null;
-      prefixPathMatch = false;
-      prefixPathMatchPattern = null;
-      return true;
-    }
-
-    // suffix patterns that contain no slash jam up my master meta-regex: the
-    // string before the $ gets put in the wrong capturing group. I fought with
-    // it
-    // a while but then bailed and just made a special meta-regex for them
-    private static final String NO_SLASH_SUFFIX_PATTERN_STRING = "\\A([^/]*)\\$\\Z";
-    private static final Pattern NO_SLASH_SUFFIX_PATTERN =
-        Pattern.compile(NO_SLASH_SUFFIX_PATTERN_STRING);
-
-    private static final String CONTAINS_PATTERNS_METAPATTERN_PREFIX = "contains:";
-
-    private static final String REGEXP_PATTERNS_METAPATTERN_PREFIX = "regexp:";
-
-    private static final String REGEXPCASE_PATTERNS_METAPATTERN_PREFIX = "regexpCase:";
-
-    private static final String REGEXPIGNORECASE_PATTERNS_METAPATTERN_PREFIX = "regexpIgnoreCase:";
-
-    private static final String UNSUPPORTED_PATTERNS_METAPATTERN_STRING = "\\A(?:(www\\?:)|(-))";
-    private static final Pattern UNSUPPORTED_PATTERNS_METAPATTERN =
-        Pattern.compile(UNSUPPORTED_PATTERNS_METAPATTERN_STRING);
-
-    private static final String OUTPUT_RIGHT_ANCHOR_PATTERN_STRING = "\\Z";
-    private static final String OUTPUT_LEFT_ANCHOR_PATTERN_STRING = "\\A";
-
-    private static final String OUTPUT_SLASH = "/";
-    private static final String OUTPUT_ANY_OR_NO_PORT_PATTERN = "(\\:[^/]*)?";
-    private static final String OUTPUT_ANY_PORT_PATTERN = "\\:[^/]*";
-
-    private static boolean isNullOrEmpty(String s) {
-      return (s == null || s.length() < 1);
-    }
-
-    // These helper functions whose names match buildSOMETHINGPattern build a
-    // regex to match the SOMETHING in their names. They should be usable,
-    // appropriately quoted regexes
-    private static String buildProtocolUserinfoHostPattern(Matcher m) {
-      StringBuilder sb = new StringBuilder();
-      sb.append(getGroup(m, MetaRegexGroup.PROTOCOL));
-      sb.append(getGroup(m, MetaRegexGroup.PROTOCOL_SEPARATOR));
-      String userInfo = getGroup(m, MetaRegexGroup.USERINFO);
-      if (!isNullOrEmpty(userInfo)) {
-        sb.append(userInfo);
-        sb.append("@");
-      }
-      sb.append(getGroup(m, MetaRegexGroup.HOST));
-      String unquotedPattern = sb.toString();
-      return isNullOrEmpty(unquotedPattern) ? "" : Pattern.quote(unquotedPattern);
-    }
-
-    // port is tricky because the absence of a port in a pattern should match
-    // any
-    // specific port in a target
-    private static String buildPortPattern(Matcher m) {
-      StringBuilder sb = new StringBuilder();
-      String port = getGroup(m, MetaRegexGroup.PORT);
-      if (isNullOrEmpty(port)) {
-        // port was empty - match any port - default or explicit
-        sb.append(OUTPUT_ANY_OR_NO_PORT_PATTERN);
-      } else {
-        if (port.equals("*")) {
-          // port was explicitly "*" - match any explicitly specified port
-          sb.append(OUTPUT_ANY_PORT_PATTERN);
-        } else {
-          // port was explicit and not "*" - match only that port
-          sb.append("\\:");
-          sb.append(Pattern.quote(port));
-        }
-      }
-      return sb.toString();
-    }
-
-    private static String buildUnquotedFilePattern(Matcher m) {
-      return getGroup(m, MetaRegexGroup.FILE);
-    }
-
-    private static String buildQuotedFilePattern(Matcher m) {
-      String unquotedPattern = buildUnquotedFilePattern(m);
-      return isNullOrEmpty(unquotedPattern) ? "" : Pattern.quote(unquotedPattern);
-    }
-
-    // the helper functions whose names match buildSOMETHINGRegex each build one
-    // of the three public regexes: the urlRegex, the protocolAuthorityRegex and
-    // the fileRegex.
-
-    // The main reason that the urlRegex is not simply the concatenation of the
-    // protocolAuthorityRegex and the fileRegex is the anchors. Both for
-    // correctness and efficiency, we want to use anchors only where
-    // appropriate:
-    // using ^A.*foo is considerably slower than just using foo.
-    private String buildUrlRegex(Matcher m) {
-      StringBuilder sb = new StringBuilder();
-      String leftAnchor = getGroup(m, MetaRegexGroup.LEFT_ANCHOR);
-      String protocolUserinfoHostPattern = buildProtocolUserinfoHostPattern(m);
-      String portPattern = buildPortPattern(m);
-      String slashAfterAuthority = getGroup(m, MetaRegexGroup.SLASH_AFTER_AUTHORITY);
-      String filePattern = buildQuotedFilePattern(m);
-      String rightAnchor = getGroup(m, MetaRegexGroup.RIGHT_ANCHOR);
-      // prefix patterns need to be handled specially
-      if (!isNullOrEmpty(leftAnchor)) {
-        sb.append(OUTPUT_LEFT_ANCHOR_PATTERN_STRING);
-      }
-      if (!isNullOrEmpty(protocolUserinfoHostPattern)) {
-        sb.append(protocolUserinfoHostPattern);
-      }
-      if (!isNullOrEmpty(portPattern)) {
-        if (sb.length() > 0) {
-          sb.append(portPattern);
-        }
-      }
-      if (!isNullOrEmpty(slashAfterAuthority)) {
-        if ("</>".equals(slashAfterAuthority)) {
-          if (sb.length() < 1) {
-            sb.append(OUTPUT_LEFT_ANCHOR_PATTERN_STRING);
-            sb.append("[^/]*//[^/]*");
-          }
-        }
-        sb.append(OUTPUT_SLASH);
-      }
-      if (!isNullOrEmpty(filePattern)) {
-        sb.append(filePattern);
-      }
-      if (!isNullOrEmpty(rightAnchor)) {
-        sb.append(rightAnchor);
-      }
-      return sb.toString();
-    }
-
-    private String buildHostRegex(Matcher m) {
-      StringBuilder sb = new StringBuilder();
-      String leftAnchor = getGroup(m, MetaRegexGroup.LEFT_ANCHOR);
-      String protocolUserinfoHostPattern = buildProtocolUserinfoHostPattern(m);
-      String portPattern = buildPortPattern(m);
-      String slashAfterAuthority = getGroup(m, MetaRegexGroup.SLASH_AFTER_AUTHORITY);
-      // prefix patterns need to be handled specially
-      if (!isNullOrEmpty(leftAnchor)) {
-        sb.append(OUTPUT_LEFT_ANCHOR_PATTERN_STRING);
-      }
-      if (!isNullOrEmpty(protocolUserinfoHostPattern)) {
-        sb.append(protocolUserinfoHostPattern);
-      }
-      if (!isNullOrEmpty(portPattern)) {
-        sb.append(portPattern);
-      }
-      if (!isNullOrEmpty(slashAfterAuthority)) {
-        sb.append(OUTPUT_SLASH);
-      }
-      return sb.toString();
-    }
-
-    // We expect that, in practice, the fileRegex will be used much more often
-    // than the protocolAuthority regex (there will probably be a hashtable for
-    // the protocol-authority portion), so we really want to makes sure that the
-    // fileRegexes are simple prefix matches, as often as possible.
-    private String buildPathRegex(Matcher m) {
-      boolean hasLeftAnchor = false;
-      boolean hasRightAnchor = false;
-      StringBuilder sb = new StringBuilder();
-      String protocolAuthority = getGroup(m, MetaRegexGroup.PROTOCOL_AUTHORITY);
-      String slashAfterAuthority = getGroup(m, MetaRegexGroup.SLASH_AFTER_AUTHORITY);
-      String unquotedFilePattern = buildUnquotedFilePattern(m);
-      String rightAnchor = getGroup(m, MetaRegexGroup.RIGHT_ANCHOR);
-      // two conditions for this being an prefix pattern:
-      // either there was a protocolAuthority OR there was a </>
-      // slashAfterAuthority
-      if (!isNullOrEmpty(protocolAuthority) || "</>".equals(slashAfterAuthority)) {
-        hasLeftAnchor = true;
-        sb.append(OUTPUT_LEFT_ANCHOR_PATTERN_STRING);
-      }
-      if (!isNullOrEmpty(slashAfterAuthority)) {
-        sb.append(OUTPUT_SLASH);
-      }
-      sb.append(Pattern.quote(unquotedFilePattern));
-      if (!isNullOrEmpty(rightAnchor)) {
-        hasRightAnchor = true;
-        sb.append(OUTPUT_RIGHT_ANCHOR_PATTERN_STRING);
-      }
-      if (hasLeftAnchor) {
-        if (hasRightAnchor) {
-          this.pathExactMatch = true;
-          this.pathExactMatchPattern = "/" + unquotedFilePattern;
-          this.prefixPathMatch = false;
-          this.prefixPathMatchPattern = null;
-        } else {
-          this.pathExactMatch = false;
-          this.pathExactMatchPattern = null;
-          this.prefixPathMatch = true;
-          this.prefixPathMatchPattern = "/" + unquotedFilePattern;
-        }
-      }
-      return sb.toString();
-    }
-
-    private static void checkPatternValidity(String s) {
-      Preconditions.checkNotNull(s);
-      Matcher m = UNSUPPORTED_PATTERNS_METAPATTERN.matcher(s);
-      Preconditions.checkArgument(!m.find(), "unsupported urlpattern: " + s);
-    }
-  }
-}
diff --git a/src/com/google/common/util/concurrent/BoundedExecutorService.java b/src/com/google/common/util/concurrent/BoundedExecutorService.java
deleted file mode 100644
index 12dd84a..0000000
--- a/src/com/google/common/util/concurrent/BoundedExecutorService.java
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2011 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.common.util.concurrent;
-
-import java.util.List;
-import java.util.concurrent.*;
-
-/**
- * Trash class to allow code to compile unmodified.
- */
-public class BoundedExecutorService extends AbstractExecutorService {
-  public BoundedExecutorService(Object ... params) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public boolean awaitTermination(long timeout, TimeUnit unit) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public boolean isShutdown() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public boolean isTerminated() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void shutdown() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public List<Runnable> shutdownNow() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void execute(Runnable command) {
-    throw new UnsupportedOperationException();
-  }
-}
diff --git a/src/com/google/enterprise/adaptor/CronScheduler.java b/src/com/google/enterprise/adaptor/CronScheduler.java
index 1cf3335..f0f260a 100644
--- a/src/com/google/enterprise/adaptor/CronScheduler.java
+++ b/src/com/google/enterprise/adaptor/CronScheduler.java
@@ -163,7 +163,8 @@
   }
 
   private static class CronPattern {
-    private static final List<Field> FIELDS = Arrays.asList(Field.values());
+    private static final List<Field> FIELDS
+        = Collections.unmodifiableList(Arrays.asList(Field.values()));
 
     private static enum Field {
       MINUTE(0, 60, Calendar.MINUTE, 0),
@@ -216,27 +217,46 @@
     // day of month: 0-30, 0 is 1st day of month.
     // month: 0-11, 0 in January.
     // day of week: 0-6, 0 is Sunday.
-    private final List<BitSet> fields;
+    // null for any value implies wildcard
+    private final EnumMap<Field, BitSet> fields;
 
-    private CronPattern(List<BitSet> fields) {
+    private CronPattern(EnumMap<Field, BitSet> fields) {
       this.fields = fields;
     }
 
     public boolean matches(Date date, TimeZone timeZone) {
       GregorianCalendar calendar = new GregorianCalendar(timeZone);
       calendar.setTime(date);
-      for (int i = 0; i < FIELDS.size(); i++) {
-        Field field = FIELDS.get(i);
-        if (!fields.get(i).get(field.calendarToIndex(calendar))) {
-          return false;
-        }
+      boolean dayMatches;
+      if (fields.get(Field.DAY_OF_MONTH) != null
+          && fields.get(Field.DAY_OF_WEEK) != null) {
+        // Both day of month and day of week are restricted, so we OR the two
+        // instead of the typical AND. This is a special case of the cron
+        // format since both fields restrict the day.
+        dayMatches = matches(Field.DAY_OF_MONTH, calendar)
+            || matches(Field.DAY_OF_WEEK, calendar);
+      } else {
+        dayMatches = matches(Field.DAY_OF_MONTH, calendar)
+            && matches(Field.DAY_OF_WEEK, calendar);
       }
-      return true;
+      return dayMatches
+          && matches(Field.MINUTE, calendar)
+          && matches(Field.HOUR, calendar)
+          && matches(Field.MONTH, calendar);
+    }
+
+    private boolean matches(Field field, Calendar calendar) {
+      BitSet bitset = fields.get(field);
+      if (bitset == null) {
+        // Wildcard.
+        return true;
+      }
+      return bitset.get(field.calendarToIndex(calendar));
     }
 
     @Override
     public String toString() {
-      return "" + fields;
+      return "" + fields.values();
     }
 
     public static CronPattern create(String timeSpecification)
@@ -248,10 +268,15 @@
             "Should have precisely 5 fields: "
             + "minute, hour, day of month, month, day of week");
       }
-      List<BitSet> fields = new ArrayList<BitSet>(FIELDS.size());
-      for (int i = 0; i < FIELDS.size(); i++) {
-        String stringField = stringFields[i];
-        Field fieldType = FIELDS.get(i);
+      EnumMap<Field, BitSet> fields = new EnumMap<Field, BitSet>(Field.class);
+      for (Field fieldType : FIELDS) {
+        String stringField = stringFields[fieldType.ordinal()];
+        if ("*".equals(stringField)) {
+          // Signal wildcard. Semantics of day of week and day of month vary
+          // based on raw wildcard vs any other value.
+          fields.put(fieldType, null);
+          continue;
+        }
         BitSet set = new BitSet(fieldType.numValues());
         for (String element : stringField.split(",", -1)) {
           int step = 1;
@@ -282,7 +307,7 @@
             }
           }
         }
-        fields.add(set);
+        fields.put(fieldType, set);
       }
       return new CronPattern(fields);
     }
diff --git a/src/com/google/enterprise/adaptor/HttpClientAdapter.java b/src/com/google/enterprise/adaptor/HttpClientAdapter.java
index 2b56d3e..ae46b16 100644
--- a/src/com/google/enterprise/adaptor/HttpClientAdapter.java
+++ b/src/com/google/enterprise/adaptor/HttpClientAdapter.java
@@ -15,8 +15,6 @@
 package com.google.enterprise.adaptor;
 
 import com.google.common.collect.ListMultimap;
-import com.google.enterprise.secmgr.common.CookieStore;
-import com.google.enterprise.secmgr.common.GCookie;
 import com.google.enterprise.secmgr.http.HttpClientInterface;
 import com.google.enterprise.secmgr.http.HttpExchange;
 
@@ -39,16 +37,6 @@
   private static final String POST_ENCODING = "UTF-8";
 
   @Override
-  public HttpExchange headExchange(URL url) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public HttpExchange getExchange(URL url) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
   public HttpExchange postExchange(URL url,
                                    ListMultimap<String, String> parameters) {
     HttpExchange exchange = new ClientExchange(url, "POST");
@@ -64,42 +52,6 @@
     return exchange;
   }
 
-  @Override
-  public HttpExchange newHttpExchange(URL url) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public Connection getConnection(URL url) throws IOException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public HttpExchange headExchange(Connection connection, URL url) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public HttpExchange getExchange(Connection connection, URL url) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public HttpExchange postExchange(Connection connection, URL url,
-                                   ListMultimap<String, String> parameters) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public HttpExchange newHttpExchange(Connection connection, URL url) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void setRequestTimeoutMillis(int millisec) {
-    throw new UnsupportedOperationException();
-  }
-
   private static class ClientExchange implements HttpExchange {
     private final URL url;
     private final String method;
@@ -182,16 +134,6 @@
       return conn.getRequestProperty(headerName);
     }
 
-    @Override
-    public void addCookies(Iterable<GCookie> cookies) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public CookieStore getCookies() {
-      throw new UnsupportedOperationException();
-    }
-
     /** Does not copy provided byte array. */
     @Override
     public void setRequestBody(byte[] byteArrayRequestEntity) {
diff --git a/src/com/google/enterprise/adaptor/SecurityManagerConfig.java b/src/com/google/enterprise/adaptor/SecurityManagerConfig.java
index 813825f..d714a86 100644
--- a/src/com/google/enterprise/adaptor/SecurityManagerConfig.java
+++ b/src/com/google/enterprise/adaptor/SecurityManagerConfig.java
@@ -14,11 +14,8 @@
 
 package com.google.enterprise.adaptor;
 
-import com.google.enterprise.secmgr.authncontroller.AuthnGuiceModule;
-import com.google.enterprise.secmgr.common.GCookie;
-import com.google.enterprise.secmgr.config.ConfigModule;
+import com.google.enterprise.secmgr.authncontroller.ExportedState;
 import com.google.enterprise.secmgr.config.ConfigSingleton;
-import com.google.enterprise.secmgr.identity.CredentialModule;
 import com.google.gson.GsonBuilder;
 
 class SecurityManagerConfig {
@@ -27,10 +24,7 @@
         new ConfigSingleton.GsonRegistrations() {
           @Override
           public void register(GsonBuilder builder) {
-            AuthnGuiceModule.registerTypeAdapters(builder);
-            ConfigModule.registerTypeAdapters(builder);
-            CredentialModule.registerTypeAdapters(builder);
-            GCookie.registerTypeAdapters(builder);
+            ExportedState.registerTypeAdapters(builder);
           }
         });
   }
diff --git a/src/com/google/enterprise/secmgr/authncontroller/AuthnGuiceModule.java b/src/com/google/enterprise/secmgr/authncontroller/AuthnGuiceModule.java
deleted file mode 100644
index eac2824..0000000
--- a/src/com/google/enterprise/secmgr/authncontroller/AuthnGuiceModule.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.authncontroller;
-
-import com.google.gson.GsonBuilder;
-/*import com.google.inject.AbstractModule;*/
-
-/**
- * Guice configuration for this package.
- */
-public final class AuthnGuiceModule /*extends AbstractModule*/ {
-
-  /*@Override
-  protected void configure() {
-    bind(AuthnController.class);
-    bind(AuthnSessionManager.class).to(AuthnSessionManagerImpl.class);
-    requestStaticInjection(AuthnSession.class);
-  }*/
-
-  public static void registerTypeAdapters(GsonBuilder builder) {
-    AuthnSessionState.registerTypeAdapters(builder);
-    ExportedState.registerTypeAdapters(builder);
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/authncontroller/AuthnSessionState.java b/src/com/google/enterprise/secmgr/authncontroller/AuthnSessionState.java
deleted file mode 100644
index b0d513f..0000000
--- a/src/com/google/enterprise/secmgr/authncontroller/AuthnSessionState.java
+++ /dev/null
@@ -1,858 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.secmgr.authncontroller;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-import com.google.common.collect.SetMultimap;
-import com.google.enterprise.secmgr.common.Chain;
-import com.google.enterprise.secmgr.common.CookieStore;
-import com.google.enterprise.secmgr.common.GCookie;
-import com.google.enterprise.secmgr.common.SecurityManagerUtil;
-import com.google.enterprise.secmgr.config.AuthnAuthority;
-import com.google.enterprise.secmgr.config.AuthnMechanism;
-import com.google.enterprise.secmgr.config.CredentialGroup;
-import com.google.enterprise.secmgr.identity.AbstractCredential;
-import com.google.enterprise.secmgr.identity.Credential;
-import com.google.enterprise.secmgr.identity.Verification;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-
-import java.lang.reflect.Type;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-import javax.annotation.concurrent.NotThreadSafe;
-
-/**
- * A representation of the state stored in an authentication session.  This is
- * not the AuthnState that's used to keep track of the what the controller is
- * doing; this is the credentials gathered by the controller.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public final class AuthnSessionState {
-
-  /**
-   * The possible instruction operations supported here.
-   */
-  public static enum Operation {
-    ADD_COOKIE(GCookie.class),
-    ADD_CREDENTIAL(Credential.class),
-    ADD_VERIFICATION(Verification.class),
-    REMOVE_COOKIE(GCookie.class),
-    REMOVE_CREDENTIAL(Credential.class),
-    REMOVE_VERIFICATION(Verification.class);
-
-    @Nonnull private final Class<?> operandClass;
-
-    private Operation(Class<?> operandClass) {
-      Preconditions.checkNotNull(operandClass);
-      this.operandClass = operandClass;
-    }
-
-    @CheckReturnValue
-    @Nonnull
-    public Class<?> getOperandClass() {
-      return operandClass;
-    }
-  }
-
-  private static final AuthnSessionState EMPTY = new AuthnSessionState(Chain.<Instruction>empty());
-
-  @Nonnull private final Chain<Instruction> instructions;
-
-  private AuthnSessionState(Chain<Instruction> instructions) {
-    Preconditions.checkNotNull(instructions);
-    this.instructions = instructions;
-  }
-
-  /**
-   * Gets an empty session state.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static AuthnSessionState empty() {
-    return EMPTY;
-  }
-
-  /**
-   * Gets a new session state with only the given verification.
-   *
-   * @param authority The authority that performed the verification process.
-   * @param verification The verification that the state will hold.
-   * @return A new state with that verification.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static AuthnSessionState of(AuthnAuthority authority, Verification verification) {
-    return empty().addVerification(authority, verification);
-  }
-
-  @VisibleForTesting
-  static AuthnSessionState of(Iterable<Instruction> instructions) {
-    return new AuthnSessionState(Chain.copyOf(instructions));
-  }
-
-  @VisibleForTesting
-  List<Instruction> getInstructions() {
-    return instructions.toList();
-  }
-
-  /**
-   * Is this state object empty?
-   *
-   * @return True only if there are no elements in this state.
-   */
-  @CheckReturnValue
-  public boolean isEmpty() {
-    return instructions.isEmpty();
-  }
-
-  /**
-   * Unit testing relies on this; it's not used in production.
-   */
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof AuthnSessionState)) { return false; }
-    AuthnSessionState other = (AuthnSessionState) object;
-    return Objects.equal(instructions, other.instructions);
-  }
-
-  /**
-   * Unit testing relies on this; it's not used in production.
-   */
-  @Override
-  public int hashCode() {
-    return Objects.hashCode(instructions);
-  }
-
-  /**
-   * Unit testing uses this for failure reporting; it's not used in production.
-   */
-  @Override
-  public String toString() {
-    StringBuilder builder = new StringBuilder();
-    for (Instruction instruction : getInstructions()) {
-      builder.append("  ");
-      builder.append(instruction);
-      builder.append("\n");
-    }
-    return builder.toString();
-  }
-
-  /**
-   * Appends some state to this state.
-   *
-   * @param delta The state to append
-   * @return A new state with that state appended.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public AuthnSessionState add(AuthnSessionState delta) {
-    return new AuthnSessionState(instructions.addAll(delta.getInstructions()));
-  }
-
-  /**
-   * Gets a session state that represents the delta between this state and a
-   * given one.  For a given ancestor state {@code A}, it is always true that
-   * {@code this.equals(A.add(this.getDelta(A)))}.
-   *
-   * @param ancestor The ancestor state to use as a reference.
-   * @return A new state with instructions that have been added since the
-   *     ancestor.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public AuthnSessionState getDelta(AuthnSessionState ancestor) {
-    return AuthnSessionState.of(instructions.toList(ancestor.instructions));
-  }
-
-  @CheckReturnValue
-  private AuthnSessionState addInstruction(Instruction instruction) {
-    Preconditions.checkNotNull(instruction);
-    return new AuthnSessionState(instructions.add(instruction));
-  }
-
-  /**
-   * Adds a cookie to this state.
-   *
-   * @param authority The authority from which the cookie was received.
-   * @param cookie The cookie to be added.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public AuthnSessionState addCookie(AuthnAuthority authority, GCookie cookie) {
-    return addInstruction(Instruction.make(Operation.ADD_COOKIE, authority, cookie));
-  }
-
-  /**
-   * Adds some cookies to this state.
-   *
-   * @param authority The authority from which the cookie was received.
-   * @param cookies The cookies to be added.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public AuthnSessionState addCookies(AuthnAuthority authority, Iterable<GCookie> cookies) {
-    AuthnSessionState state = this;
-    for (GCookie cookie : cookies) {
-      state = state.addCookie(authority, cookie);
-    }
-    return state;
-  }
-
-  /**
-   * Removes a cookie from this state.
-   *
-   * @param authority The authority from which the cookie was originally received.
-   * @param cookie The cookie to be removed.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public AuthnSessionState removeCookie(AuthnAuthority authority, GCookie cookie) {
-    return addInstruction(Instruction.make(Operation.REMOVE_COOKIE, authority, cookie));
-  }
-
-  /**
-   * Removes some cookies from this state.
-   *
-   * @param authority The authority from which the cookie was received.
-   * @param cookies The cookies to be removed.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public AuthnSessionState removeCookies(AuthnAuthority authority, Iterable<GCookie> cookies) {
-    AuthnSessionState state = this;
-    for (GCookie cookie : cookies) {
-      state = state.removeCookie(authority, cookie);
-    }
-    return state;
-  }
-
-  /**
-   * Adds a credential to this state.
-   *
-   * @param authority The authority from which the credential was received.
-   * @param credential The credential to be added.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public AuthnSessionState addCredential(AuthnAuthority authority, Credential credential) {
-    return addInstruction(Instruction.make(Operation.ADD_CREDENTIAL, authority, credential));
-  }
-
-  /**
-   * Adds some credentials to this state.
-   *
-   * @param authority The authority from which the cookie was received.
-   * @param credentials The credentials to be added.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public AuthnSessionState addCredentials(AuthnAuthority authority,
-      Iterable<Credential> credentials) {
-    AuthnSessionState state = this;
-    for (Credential credential : credentials) {
-      state = state.addCredential(authority, credential);
-    }
-    return state;
-  }
-
-  /**
-   * Removes a credential from this state.
-   *
-   * @param authority The authority from which the credential was originally received.
-   * @param credential The credential to be removed.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public AuthnSessionState removeCredential(AuthnAuthority authority,
-      Credential credential) {
-    return addInstruction(Instruction.make(Operation.REMOVE_CREDENTIAL, authority, credential));
-  }
-
-  /**
-   * Adds a verification to this state.
-   *
-   * @param authority The authority that performed the verification process.
-   * @param verification The verification to be added.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public AuthnSessionState addVerification(AuthnAuthority authority, Verification verification) {
-    return addInstruction(Instruction.make(Operation.ADD_VERIFICATION, authority, verification));
-  }
-
-  /**
-   * Adds some verifications to this state.
-   *
-   * @param authority The authority that performed the verification process.
-   * @param verifications The verifications to be added.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public AuthnSessionState addVerifications(AuthnAuthority authority,
-      Iterable<Verification> verifications) {
-    AuthnSessionState state = this;
-    for (Verification verification : verifications) {
-      state = state.addVerification(authority, verification);
-    }
-    return state;
-  }
-
-  /**
-   * Removes a verification from this state.
-   *
-   * @param authority The authority that performed the verification process.
-   * @param verification The verification to be removed.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public AuthnSessionState removeVerification(AuthnAuthority authority, Verification verification) {
-    return addInstruction(Instruction.make(Operation.REMOVE_VERIFICATION, authority, verification));
-  }
-
-  /**
-   * Removes some verifications from this state.
-   *
-   * @param authority The authority that performed the verification process.
-   * @param verifications The verifications to be removed.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public AuthnSessionState removeVerifications(AuthnAuthority authority,
-      Iterable<Verification> verifications) {
-    AuthnSessionState state = this;
-    for (Verification verification : verifications) {
-      state = state.removeVerification(authority, verification);
-    }
-    return state;
-  }
-
-  /**
-   * Computes a summary of this state's contents.
-   *
-   * @param credentialGroups The credential groups associated with this session.
-   * @return An immutable summary of the state's contents.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public Summary computeSummary(Iterable<CredentialGroup> credentialGroups) {
-    return evolveSummary(new Evolver(credentialGroups));
-  }
-
-  /**
-   * Computes a summary by extending a given summary with this state's contents.
-   *
-   * @param summary The summary to be extended.
-   * @return An immutable extended summary.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public Summary evolveSummary(Summary summary) {
-    return evolveSummary(summary.evolve());
-  }
-
-  private Summary evolveSummary(Evolver evolver) {
-    for (Instruction instruction : getInstructions()) {
-      AuthnAuthority authority = instruction.getAuthority();
-      Object operand = instruction.getOperand();
-      switch (instruction.getOperation()) {
-        case ADD_COOKIE:
-          evolver.addCookie(authority, (GCookie) operand);
-          break;
-        case REMOVE_COOKIE:
-          evolver.removeCookie(authority, (GCookie) operand);
-          break;
-        case ADD_CREDENTIAL:
-          evolver.addCredential(authority, (Credential) operand);
-          break;
-        case REMOVE_CREDENTIAL:
-          evolver.removeCredential(authority, (Credential) operand);
-          break;
-        case ADD_VERIFICATION:
-          evolver.addVerification(authority, (Verification) operand);
-          break;
-        case REMOVE_VERIFICATION:
-          evolver.removeVerification(authority, (Verification) operand);
-          break;
-        default:
-          throw new IllegalStateException("Unknown instruction operation: "
-              + instruction.getOperation());
-      }
-    }
-    return evolver.getSummary();
-  }
-
-  @NotThreadSafe
-  @ParametersAreNonnullByDefault
-  private static final class Evolver {
-    @Nonnull final ImmutableList<CredentialGroup> credentialGroups;
-    @Nonnull final Map<AuthnAuthority, CookieStore> cookiesMap;
-    @Nonnull final SetMultimap<AuthnAuthority, Credential> credentialsMap;
-    @Nonnull final Map<AuthnAuthority, Verification> verificationsMap;
-
-    Evolver(Iterable<CredentialGroup> credentialGroups) {
-      this.credentialGroups = ImmutableList.copyOf(credentialGroups);
-      cookiesMap = Maps.<AuthnAuthority, CookieStore>newHashMap();
-      credentialsMap = HashMultimap.<AuthnAuthority, Credential>create();
-      verificationsMap = Maps.<AuthnAuthority, Verification>newHashMap();
-    }
-
-    Evolver(ImmutableList<CredentialGroup> credentialGroups,
-        ImmutableMap<AuthnAuthority, ImmutableSet<GCookie>> cookiesMap,
-        ImmutableSetMultimap<AuthnAuthority, Credential> credentialsMap,
-        ImmutableMap<AuthnAuthority, Verification> verificationsMap) {
-      this.credentialGroups = credentialGroups;
-      this.cookiesMap = thawCookiesMap(cookiesMap);
-      this.credentialsMap = HashMultimap.create(credentialsMap);
-      this.verificationsMap = Maps.newHashMap(verificationsMap);
-    }
-
-    static Map<AuthnAuthority, CookieStore> thawCookiesMap(
-        ImmutableMap<AuthnAuthority, ImmutableSet<GCookie>> cookiesMap) {
-      Map<AuthnAuthority, CookieStore> result = Maps.newHashMap();
-      for (Map.Entry<AuthnAuthority, ImmutableSet<GCookie>> entry : cookiesMap.entrySet()) {
-        CookieStore cookies = GCookie.makeStore();
-        cookies.addAll(entry.getValue());
-        result.put(entry.getKey(), cookies);
-      }
-      return result;
-    }
-
-    Summary getSummary() {
-      return new Summary(credentialGroups, freezeCookiesMap(),
-          ImmutableSetMultimap.copyOf(credentialsMap), ImmutableMap.copyOf(verificationsMap));
-    }
-
-    ImmutableMap<AuthnAuthority, ImmutableSet<GCookie>> freezeCookiesMap() {
-      ImmutableMap.Builder<AuthnAuthority, ImmutableSet<GCookie>> builder = ImmutableMap.builder();
-      for (Map.Entry<AuthnAuthority, CookieStore> entry : cookiesMap.entrySet()) {
-        builder.put(entry.getKey(), ImmutableSet.copyOf(entry.getValue()));
-      }
-      return builder.build();
-    }
-
-    void addCookie(AuthnAuthority authority, GCookie cookie) {
-      getCookies(authority).add(cookie);
-    }
-
-    void removeCookie(AuthnAuthority authority, GCookie cookie) {
-      getCookies(authority).remove(cookie);
-    }
-
-    CookieStore getCookies(AuthnAuthority authority) {
-      CookieStore cookies = cookiesMap.get(authority);
-      if (cookies == null) {
-        cookies = GCookie.makeStore();
-        cookiesMap.put(authority, cookies);
-      }
-      return cookies;
-    }
-
-    void addCredential(AuthnAuthority authority, Credential credential) {
-      AuthnAuthority cgAuthority = getCredGroupAuthority(authority);
-      if (!credentialsMap.containsEntry(cgAuthority, credential)) {
-        Iterable<Credential> removed
-            = SecurityManagerUtil.removeInPlace(credentialsMap.get(cgAuthority),
-                AbstractCredential.getTypePredicate(credential.getClass()));
-        for (AuthnAuthority mechAuthority : getMechAuthorities(cgAuthority)) {
-          Verification verification = verificationsMap.get(mechAuthority);
-          if (verification != null && verification.containsAnyCredential(removed)) {
-            verificationsMap.remove(mechAuthority);
-          }
-        }
-        credentialsMap.put(cgAuthority, credential);
-      }
-    }
-
-    void removeCredential(AuthnAuthority authority, Credential credential) {
-      AuthnAuthority cgAuthority = getCredGroupAuthority(authority);
-      if (credentialsMap.containsEntry(cgAuthority, credential)) {
-        for (AuthnAuthority mechAuthority : getMechAuthorities(cgAuthority)) {
-          Verification verification = verificationsMap.get(mechAuthority);
-          if (verification != null && verification.containsCredential(credential)) {
-            verificationsMap.remove(mechAuthority);
-          }
-        }
-        credentialsMap.remove(cgAuthority, credential);
-      }
-    }
-
-    void addVerification(AuthnAuthority authority, Verification verification) {
-      verificationsMap.put(authority, verification);
-      for (Credential credential : verification.getCredentials()) {
-        addCredential(authority, credential);
-      }
-    }
-
-    void removeVerification(AuthnAuthority authority, Verification verification) {
-      if (verification.equals(verificationsMap.get(authority))) {
-        verificationsMap.remove(authority);
-      }
-    }
-
-    AuthnAuthority getCredGroupAuthority(AuthnAuthority authority) {
-      for (CredentialGroup credentialGroup : credentialGroups) {
-        for (AuthnMechanism mechanism : credentialGroup.getMechanisms()) {
-          if (authority.equals(mechanism.getAuthority())) {
-            return credentialGroup.getAuthority();
-          }
-        }
-      }
-      return authority;
-    }
-
-    Iterable<AuthnAuthority> getMechAuthorities(AuthnAuthority authority) {
-      for (CredentialGroup credentialGroup : credentialGroups) {
-        if (authority.equals(credentialGroup.getAuthority())) {
-          return Iterables.transform(credentialGroup.getMechanisms(),
-              AuthnMechanism.getAuthorityFunction());
-        }
-      }
-      return ImmutableList.of(authority);
-    }
-  }
-
-  /**
-   * The result of {@link #computeSummary}, this structure contains a summary of
-   * the session state as computed by executing the session-state's
-   * instructions.
-   */
-  @Immutable
-  @ParametersAreNonnullByDefault
-  public static final class Summary {
-    @Nonnull private final ImmutableList<CredentialGroup> credentialGroups;
-    @Nonnull private final ImmutableMap<AuthnAuthority, ImmutableSet<GCookie>> cookiesMap;
-    @Nonnull private final ImmutableSetMultimap<AuthnAuthority, Credential> credentialsMap;
-    @Nonnull private final ImmutableMap<AuthnAuthority, Verification> verificationsMap;
-
-    private Summary(ImmutableList<CredentialGroup> credentialGroups,
-        ImmutableMap<AuthnAuthority, ImmutableSet<GCookie>> cookiesMap,
-        ImmutableSetMultimap<AuthnAuthority, Credential> credentialsMap,
-        ImmutableMap<AuthnAuthority, Verification> verificationsMap) {
-      this.credentialGroups = credentialGroups;
-      this.cookiesMap = cookiesMap;
-      this.credentialsMap = credentialsMap;
-      this.verificationsMap = verificationsMap;
-    }
-
-    @CheckReturnValue
-    @Nonnull
-    private Evolver evolve() {
-      return new Evolver(credentialGroups, cookiesMap, credentialsMap, verificationsMap);
-    }
-
-    /**
-     * Gets the credential groups that were used to generate this summary.
-     */
-    @CheckReturnValue
-    @Nonnull
-    public ImmutableList<CredentialGroup> getCredentialGroups() {
-      return credentialGroups;
-    }
-
-    /**
-     * Gets all the cookies in this summary.
-     *
-     * @return An immutable map of the cookies for each authority.
-     */
-    @CheckReturnValue
-    @Nonnull
-    public ImmutableMap<AuthnAuthority, ImmutableSet<GCookie>> getCookiesMap() {
-      return cookiesMap;
-    }
-
-    /**
-     * Gets all the credentials in this summary.
-     *
-     * @return An immutable map of the credentials for each authority.
-     */
-    public ImmutableSetMultimap<AuthnAuthority, Credential> getCredentialsMap() {
-      return credentialsMap;
-    }
-
-    /**
-     * Gets all the verifications in this summary.
-     *
-     * @return An immutable map of the verifications for each authority.
-     */
-    @CheckReturnValue
-    @Nonnull
-    public ImmutableMap<AuthnAuthority, Verification> getVerificationsMap() {
-      return verificationsMap;
-    }
-
-    /**
-     * Gets the cookies in this summary for some specified authorities.
-     *
-     * @param predicate A predicate specifying the authorities to get cookies for.
-     * @return An immutable set of the cookies for the matching authorities.
-     */
-    @CheckReturnValue
-    @Nonnull
-    public ImmutableSet<GCookie> getCookies(Predicate<AuthnAuthority> predicate) {
-      ImmutableSet.Builder<GCookie> builder = ImmutableSet.builder();
-      for (Map.Entry<AuthnAuthority, ImmutableSet<GCookie>> entry : cookiesMap.entrySet()) {
-        if (predicate.apply(entry.getKey())) {
-          builder.addAll(entry.getValue());
-        }
-      }
-      return builder.build();
-    }
-
-    /**
-     * Gets the unexpired cookies in this summary for some specified authorities.
-     *
-     * @param predicate A predicate specifying the authorities to get cookies for.
-     * @param timeStamp A reference time to use for expiring cookies.
-     * @return An immutable set of the unexpired cookies for the matching authorities.
-     */
-    @CheckReturnValue
-    @Nonnull
-    public ImmutableSet<GCookie> getCookies(Predicate<AuthnAuthority> predicate, long timeStamp) {
-      ImmutableSet.Builder<GCookie> builder = ImmutableSet.builder();
-      for (Map.Entry<AuthnAuthority, ImmutableSet<GCookie>> entry : cookiesMap.entrySet()) {
-        if (predicate.apply(entry.getKey())) {
-          for (GCookie cookie : entry.getValue()) {
-            if (!cookie.isExpired(timeStamp)) {
-              builder.add(cookie);
-            }
-          }
-        }
-      }
-      return builder.build();
-    }
-
-    /**
-     * Gets the credentials in this summary for some specified authorities.
-     *
-     * @param predicate A predicate specifying the authorities to get credentials for.
-     * @return An immutable set of the credentials for the matching authorities.
-     */
-    @CheckReturnValue
-    @Nonnull
-    public ImmutableSet<Credential> getCredentials(Predicate<AuthnAuthority> predicate) {
-      ImmutableSet.Builder<Credential> builder = ImmutableSet.builder();
-      for (AuthnAuthority authority : credentialsMap.keySet()) {
-        if (predicate.apply(authority)) {
-          builder.addAll(credentialsMap.get(authority));
-        }
-      }
-      return builder.build();
-    }
-
-    /**
-     * Gets the verifications in this summary for some specified authorities.
-     *
-     * @param predicate A predicate specifying the authorities to get verifications for.
-     * @return An immutable set of the verifications for the matching authorities.
-     */
-    @CheckReturnValue
-    @Nonnull
-    public ImmutableSet<Verification> getVerifications(Predicate<AuthnAuthority> predicate) {
-      ImmutableSet.Builder<Verification> builder = ImmutableSet.builder();
-      for (Map.Entry<AuthnAuthority, Verification> entry : verificationsMap.entrySet()) {
-        if (predicate.apply(entry.getKey())) {
-          builder.add(entry.getValue());
-        }
-      }
-      return builder.build();
-    }
-
-    /**
-     * Gets the unexpired verifications in this summary for some specified authorities.
-     *
-     * @param predicate A predicate specifying the authorities to get verifications for.
-     * @param timeStamp A reference time to use for expiring verifications.
-     * @return An immutable set of the unexpired verifications for the matching authorities.
-     */
-    @CheckReturnValue
-    @Nonnull
-    public ImmutableSet<Verification> getVerifications(Predicate<AuthnAuthority> predicate,
-        long timeStamp) {
-      ImmutableSet.Builder<Verification> builder = ImmutableSet.builder();
-      for (Map.Entry<AuthnAuthority, Verification> entry : verificationsMap.entrySet()) {
-        if (predicate.apply(entry.getKey())) {
-          Verification verification = entry.getValue();
-          if (!verification.hasExpired(timeStamp)) {
-            builder.add(verification);
-          }
-        }
-      }
-      return builder.build();
-    }
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(AuthnSessionState.class,
-        ProxyTypeAdapter.make(AuthnSessionState.class, LocalProxy.class));
-    builder.registerTypeAdapter(Instruction.class,
-        new Instruction.LocalTypeAdapter());
-  }
-
-  private static final class LocalProxy implements TypeProxy<AuthnSessionState> {
-    List<Instruction> instructions;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(AuthnSessionState state) {
-      instructions = state.getInstructions();
-    }
-
-    @Override
-    public AuthnSessionState build() {
-      return AuthnSessionState.of(instructions);
-    }
-  }
-
-  /**
-   * An instruction, consisting of an operation, an authority, and an operand.
-   */
-  @Immutable
-  @ParametersAreNonnullByDefault
-  public static final class Instruction {
-    @Nonnull private final Operation operation;
-    @Nonnull private final AuthnAuthority authority;
-    @Nonnull private final Object operand;
-
-    private Instruction(Operation operation, AuthnAuthority authority, Object operand) {
-      this.operation = operation;
-      this.authority = authority;
-      this.operand = operand;
-    }
-
-    @CheckReturnValue
-    @Nonnull
-    public static Instruction make(Operation operation, AuthnAuthority authority, Object operand) {
-      Preconditions.checkNotNull(authority);
-      Preconditions.checkArgument(operation.getOperandClass().isInstance(operand));
-      return new Instruction(operation, authority, operand);
-    }
-
-    @CheckReturnValue
-    @Nonnull
-    public Operation getOperation() {
-      return operation;
-    }
-
-    @CheckReturnValue
-    @Nonnull
-    public AuthnAuthority getAuthority() {
-      return authority;
-    }
-
-    @CheckReturnValue
-    @Nonnull
-    public Object getOperand() {
-      return operand;
-    }
-
-    @Override
-    public boolean equals(Object object) {
-      if (object == this) { return true; }
-      if (!(object instanceof Instruction)) { return false; }
-      Instruction other = (Instruction) object;
-      return Objects.equal(getOperation(), other.getOperation())
-          && Objects.equal(getAuthority(), other.getAuthority())
-          && Objects.equal(getOperand(), other.getOperand());
-    }
-
-    @Override
-    public int hashCode() {
-      return Objects.hashCode(getOperation(), getAuthority(), getOperand());
-    }
-
-    @Override
-    public String toString() {
-      StringBuilder builder = new StringBuilder();
-      switch (operation) {
-        case ADD_COOKIE:
-        case ADD_CREDENTIAL:
-        case ADD_VERIFICATION:
-          builder.append("add to ");
-          break;
-        case REMOVE_COOKIE:
-        case REMOVE_CREDENTIAL:
-        case REMOVE_VERIFICATION:
-          builder.append("remove from ");
-          break;
-        default:
-          throw new IllegalStateException("Unknown operation: " + operation);
-      }
-      builder.append(authority);
-      builder.append(": ");
-      builder.append(operand);
-      return builder.toString();
-    }
-
-    private static final class LocalTypeAdapter
-        implements JsonSerializer<Instruction>, JsonDeserializer<Instruction> {
-      static final String KEY_OPERATION = "operation";
-      static final String KEY_AUTHORITY = "authority";
-      static final String KEY_OPERAND = "operand";
-
-      LocalTypeAdapter() {
-      }
-
-      @Override
-      public JsonElement serialize(Instruction instruction, Type type,
-          JsonSerializationContext context) {
-        JsonObject jo = new JsonObject();
-        Operation operation = instruction.getOperation();
-        jo.addProperty(KEY_OPERATION, operation.toString());
-        jo.add(KEY_AUTHORITY, context.serialize(instruction.getAuthority(), AuthnAuthority.class));
-        jo.add(KEY_OPERAND,
-            context.serialize(instruction.getOperand(), operation.getOperandClass()));
-        return jo;
-      }
-
-      @Override
-      public Instruction deserialize(JsonElement src, Type type,
-          JsonDeserializationContext context) {
-        JsonObject jo = src.getAsJsonObject();
-        Operation operation = Operation.valueOf(jo.getAsJsonPrimitive(KEY_OPERATION).getAsString());
-        AuthnAuthority authority = context.deserialize(jo.get(KEY_AUTHORITY), AuthnAuthority.class);
-        return Instruction.make(operation, authority,
-            context.deserialize(jo.get(KEY_OPERAND), operation.getOperandClass()));
-      }
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/authncontroller/ExportedState.java b/src/com/google/enterprise/secmgr/authncontroller/ExportedState.java
index aa8e748..203bbbe 100644
--- a/src/com/google/enterprise/secmgr/authncontroller/ExportedState.java
+++ b/src/com/google/enterprise/secmgr/authncontroller/ExportedState.java
@@ -18,14 +18,7 @@
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
-import com.google.enterprise.secmgr.common.GCookie;
-import com.google.enterprise.secmgr.config.AuthnMechBasic;
-import com.google.enterprise.secmgr.config.AuthnMechConnector;
-import com.google.enterprise.secmgr.config.AuthnMechLdap;
-import com.google.enterprise.secmgr.config.AuthnMechNtlm;
-import com.google.enterprise.secmgr.config.AuthnMechanism;
 import com.google.enterprise.secmgr.config.ConfigSingleton;
-import com.google.enterprise.secmgr.http.ConnectorUtil;
 import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
 import com.google.enterprise.secmgr.json.TypeAdapters;
 import com.google.enterprise.secmgr.json.TypeProxy;
@@ -191,78 +184,18 @@
 
   @Nonnegative private final int version;
   @Nonnegative private final long timeStamp;
-  @Nonnull private final AuthnSessionState sessionState;
   @Nonnull private final Credentials pviCredentials;
   @Nonnull private final Credentials basicCredentials;
   @Nonnull private final ImmutableMap<String, Credentials> connectorCredentials;
-  @Nonnull private final ImmutableSet<GCookie> cookies;
 
   private ExportedState(@Nonnegative int version, @Nonnegative long timeStamp,
-      AuthnSessionState sessionState, Credentials pviCredentials, Credentials basicCredentials,
-      ImmutableMap<String, Credentials> connectorCredentials, ImmutableSet<GCookie> cookies) {
+      Credentials pviCredentials, Credentials basicCredentials,
+      ImmutableMap<String, Credentials> connectorCredentials) {
     this.version = version;
     this.timeStamp = timeStamp;
-    this.sessionState = sessionState;
     this.pviCredentials = pviCredentials;
     this.basicCredentials = basicCredentials;
     this.connectorCredentials = connectorCredentials;
-    this.cookies = cookies;
-  }
-
-  /**
-   * Makes an exported-state object from a given session snapshot.
-   *
-   * @param snapshot A snapshot to derive the exported state from.
-   * @return A corresponding exported-state object.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static ExportedState make(SessionSnapshot snapshot) {
-    long timeStamp = snapshot.getTimeStamp();
-    Credentials pviCredentials
-        = credentialsForView(snapshot.getPrimaryVerifiedView(), Credentials.EMPTY);
-    Credentials basicCredentials = credentialsForView(getBasicView(snapshot), pviCredentials);
-    ImmutableMap.Builder<String, Credentials> connectorCredentialsBuilder = ImmutableMap.builder();
-    for (String instanceName : ConnectorUtil.getUrlMap().keySet()) {
-      connectorCredentialsBuilder.put(instanceName,
-          credentialsForView(findConnectorView(instanceName, snapshot), pviCredentials));
-    }
-    ImmutableMap<String, Credentials> connectorCredentials = connectorCredentialsBuilder.build();
-    ImmutableSet<GCookie> cookies = ImmutableSet.copyOf(snapshot.getView().getAuthorityCookies());
-    return new ExportedState(CURRENT_VERSION, timeStamp, snapshot.getState(), pviCredentials,
-        basicCredentials, connectorCredentials, cookies);
-  }
-
-  private static Credentials credentialsForView(SessionView view, Credentials fallback) {
-    if (view == null) {
-      return fallback;
-    }
-    if (view.hasVerifiedPrincipalAndPassword()) {
-      return Credentials.make(view.getUsername(), view.getDomain(), view.getPassword(),
-          view.getGroups());
-    }
-    return Credentials.EMPTY;
-  }
-
-  private static SessionView getBasicView(SessionSnapshot snapshot) {
-    for (AuthnMechanism mechanism : snapshot.getConfig().getMechanisms()) {
-      if (mechanism instanceof AuthnMechBasic
-          || mechanism instanceof AuthnMechLdap
-          || mechanism instanceof AuthnMechNtlm) {
-        return snapshot.getView(mechanism);
-      }
-    }
-    return null;
-  }
-
-  private static SessionView findConnectorView(String instanceName, SessionSnapshot snapshot) {
-    for (AuthnMechanism mechanism : snapshot.getConfig().getMechanisms()) {
-      if (mechanism instanceof AuthnMechConnector
-          && instanceName.equals(((AuthnMechConnector) mechanism).getConnectorName())) {
-        return snapshot.getView(mechanism);
-      }
-    }
-    return null;
   }
 
   /**
@@ -275,16 +208,6 @@
   }
 
   /**
-   * Gets the security manager's session state, consisting of all cookies,
-   * credentials, and verifications generated during authentication.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public AuthnSessionState getSessionState() {
-    return sessionState;
-  }
-
-  /**
    * Gets the credentials for the Primary Verified Identity (PVI).
    */
   @CheckReturnValue
@@ -314,15 +237,6 @@
   }
 
   /**
-   * Gets all the cookies collected by the security manager.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public ImmutableSet<GCookie> getCookies() {
-    return cookies;
-  }
-
-  /**
    * Gets a JSON string representation for this object.
    */
   @CheckReturnValue
@@ -340,15 +254,13 @@
     return ConfigSingleton.getGson().fromJson(jsonString, ExportedState.class);
   }
 
-  static void registerTypeAdapters(GsonBuilder builder) {
+  public static void registerTypeAdapters(GsonBuilder builder) {
     builder.registerTypeAdapter(Credentials.class,
         ProxyTypeAdapter.make(Credentials.class, Credentials.LocalProxy.class));
     builder.registerTypeAdapter(ExportedState.class,
         ProxyTypeAdapter.make(ExportedState.class, LocalProxy.class));
     builder.registerTypeAdapter(new TypeToken<ImmutableSet<String>>() {}.getType(),
         TypeAdapters.immutableSet());
-    builder.registerTypeAdapter(new TypeToken<ImmutableSet<GCookie>>() {}.getType(),
-        TypeAdapters.immutableSet());
     builder.registerTypeAdapter(new TypeToken<ImmutableMap<String, Credentials>>() {}.getType(),
         TypeAdapters.immutableMap());
   }
@@ -356,11 +268,9 @@
   private static final class LocalProxy implements TypeProxy<ExportedState> {
     int version;
     long timeStamp;
-    AuthnSessionState sessionState;
     Credentials pviCredentials;
     Credentials basicCredentials;
     ImmutableMap<String, Credentials> connectorCredentials;
-    ImmutableSet<GCookie> cookies;
 
     @SuppressWarnings("unused")
     LocalProxy() {
@@ -370,20 +280,17 @@
     LocalProxy(ExportedState state) {
       version = state.version;
       timeStamp = state.timeStamp;
-      sessionState = state.getSessionState();
       pviCredentials = state.getPviCredentials();
       basicCredentials = state.getBasicCredentials();
       connectorCredentials = state.getConnectorCredentials();
-      cookies = state.getCookies();
     }
 
     @Override
     public ExportedState build() {
       Preconditions.checkArgument(version >= MIN_VERSION && version <= MAX_VERSION);
       Preconditions.checkArgument(timeStamp >= 0);
-      Preconditions.checkArgument(sessionState != null);
-      return new ExportedState(version, timeStamp, sessionState, pviCredentials, basicCredentials,
-          ImmutableMap.copyOf(connectorCredentials), ImmutableSet.copyOf(cookies));
+      return new ExportedState(version, timeStamp, pviCredentials, basicCredentials,
+          ImmutableMap.copyOf(connectorCredentials));
     }
   }
 }
diff --git a/src/com/google/enterprise/secmgr/authncontroller/SessionSnapshot.java b/src/com/google/enterprise/secmgr/authncontroller/SessionSnapshot.java
deleted file mode 100644
index c18e187..0000000
--- a/src/com/google/enterprise/secmgr/authncontroller/SessionSnapshot.java
+++ /dev/null
@@ -1,234 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.secmgr.authncontroller;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Maps;
-import com.google.enterprise.secmgr.common.GCookie;
-import com.google.enterprise.secmgr.common.SecurityManagerUtil;
-import com.google.enterprise.secmgr.common.SessionUtil;
-import com.google.enterprise.secmgr.config.AuthnMechanism;
-import com.google.enterprise.secmgr.config.CredentialGroup;
-import com.google.enterprise.secmgr.config.SecurityManagerConfig;
-import com.google.enterprise.secmgr.identity.Verification;
-
-import org.joda.time.DateTimeUtils;
-import org.joda.time.format.ISODateTimeFormat;
-
-import java.net.URL;
-import java.util.Map;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnegative;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.GuardedBy;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * An immutable snapshot of the session's state.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public final class SessionSnapshot {
-  @Nonnull private final String sessionId;
-  @Nonnull private final SecurityManagerConfig config;
-  @Nullable private final URL authnEntryUrl;
-  @Nonnull private final ImmutableCollection<GCookie> userAgentCookies;
-  @Nonnull private final AuthnSessionState state;
-  @Nonnegative private final long timeStamp;
-  @Nonnull private final SessionView unspecializedView;
-  @GuardedBy("itself")
-  @Nonnull private final Map<AuthnMechanism, SessionView> savedMechanismViews;
-  @GuardedBy("itself")
-  @Nonnull private final Map<CredentialGroup, SessionView> savedCredentialGroupViews;
-
-  private SessionSnapshot(String sessionId, SecurityManagerConfig config,
-      @Nullable URL authnEntryUrl, ImmutableCollection<GCookie> userAgentCookies,
-      AuthnSessionState state, @Nonnegative long timeStamp) {
-    this.sessionId = sessionId;
-    this.config = config;
-    this.authnEntryUrl = authnEntryUrl;
-    this.userAgentCookies = userAgentCookies;
-    this.state = state;
-    this.timeStamp = timeStamp;
-    unspecializedView = SessionView.create(this);
-    savedMechanismViews = Maps.newHashMap();
-    savedCredentialGroupViews = Maps.newHashMap();
-  }
-
-  static SessionSnapshot make(String sessionId, SecurityManagerConfig config,
-      @Nullable URL authnEntryUrl, ImmutableCollection<GCookie> userAgentCookies,
-      AuthnSessionState state) {
-    return new SessionSnapshot(sessionId, config, authnEntryUrl, userAgentCookies,
-        state, DateTimeUtils.currentTimeMillis());
-  }
-
-  @VisibleForTesting
-  public static SessionSnapshot make(SecurityManagerConfig config, AuthnSessionState state) {
-    return make(SessionUtil.generateId(), config, null, ImmutableList.<GCookie>of(), state);
-  }
-
-  SessionSnapshot withNewUserAgentCookies(ImmutableCollection<GCookie> userAgentCookies) {
-    return new SessionSnapshot(sessionId, config, authnEntryUrl, userAgentCookies,
-        state, timeStamp);
-  }
-
-  @CheckReturnValue
-  @Nonnull
-  public String getSessionId() {
-    return sessionId;
-  }
-
-  @CheckReturnValue
-  @Nonnull
-  public SecurityManagerConfig getConfig() {
-    return config;
-  }
-
-  @CheckReturnValue
-  @Nullable
-  URL getAuthnEntryUrl() {
-    return authnEntryUrl;
-  }
-
-  @CheckReturnValue
-  @Nonnull
-  ImmutableCollection<GCookie> getUserAgentCookies() {
-    return userAgentCookies;
-  }
-
-  @CheckReturnValue
-  @Nonnull
-  public AuthnSessionState getState() {
-    return state;
-  }
-
-  @CheckReturnValue
-  @Nonnegative
-  long getTimeStamp() {
-    return timeStamp;
-  }
-
-  /**
-   * Gets a view of this snapshot specialized for a given authentication
-   * mechanism.
-   *
-   * @param mechanism An authentication mechanism.
-   * @return A mechanism view of this snapshot.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public SessionView getView(AuthnMechanism mechanism) {
-    synchronized (savedMechanismViews) {
-      SessionView view = savedMechanismViews.get(mechanism);
-      if (view == null) {
-        view = SessionView.create(this, mechanism);
-        savedMechanismViews.put(mechanism, view);
-      }
-      return view;
-    }
-  }
-
-  /**
-   * Gets a view of this snapshot specialized for a given credential group.
-   *
-   * @param credentialGroup A credential group.
-   * @return A credential-group view of this snapshot.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public SessionView getView(CredentialGroup credentialGroup) {
-    synchronized (savedCredentialGroupViews) {
-      SessionView view = savedCredentialGroupViews.get(credentialGroup);
-      if (view == null) {
-        view = SessionView.create(this, credentialGroup);
-        savedCredentialGroupViews.put(credentialGroup, view);
-      }
-      return view;
-    }
-  }
-
-  /**
-   * Gets an unspecialized view of this snapshot.
-   *
-   * @return An unspecialized view of this snapshot.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public SessionView getView() {
-    return unspecializedView;
-  }
-
-  /**
-   * Gets the expiration time for this snapshot.
-   *
-   * @return The expiration time.
-   */
-  @CheckReturnValue
-  public long getExpirationTime() {
-    SessionView view = getView();
-    return view.isSatisfied()
-        ? Verification.minimumExpirationTime(view.getVerifications())
-        : timeStamp;
-  }
-
-  /**
-   * Get a "primary verified view".  This is a view containing a principal
-   * that's been verified, with preference given to the default credential
-   * group's view, if possible.
-   *
-   * <p>The primary verified view is intended for use by the GSA, and this
-   * method is only called when generating output for the GSA.  It should
-   * <b>never</b> be used for any other purpose.
-   *
-   * @return The primary verified view, or null if there isn't one.
-   */
-  public SessionView getPrimaryVerifiedView() {
-    SessionView winner = null;
-    for (CredentialGroup credentialGroup : getConfig().getCredentialGroups()) {
-      SessionView view = getView(credentialGroup);
-      if (view.hasVerifiedPrincipal()) {
-        if (credentialGroup.isDefault()) {
-          return view;
-        }
-        if (winner == null) {
-          winner = view;
-        }
-      }
-    }
-    return winner;
-  }
-
-  @CheckReturnValue
-  @Nonnull
-  public String logMessage(String format, Object... args) {
-    return SecurityManagerUtil.sessionLogMessage(sessionId, String.format(format, args));
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder builder = new StringBuilder();
-    builder.append("{SessionSnapshot taken at ");
-    builder.append(ISODateTimeFormat.dateTime().print(timeStamp));
-    builder.append(" of session ");
-    builder.append(sessionId);
-    builder.append("}");
-    return builder.toString();
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/authncontroller/SessionView.java b/src/com/google/enterprise/secmgr/authncontroller/SessionView.java
deleted file mode 100644
index 1fd6157..0000000
--- a/src/com/google/enterprise/secmgr/authncontroller/SessionView.java
+++ /dev/null
@@ -1,643 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.secmgr.authncontroller;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.enterprise.secmgr.common.GCookie;
-import com.google.enterprise.secmgr.config.AuthnAuthority;
-import com.google.enterprise.secmgr.config.AuthnMechanism;
-import com.google.enterprise.secmgr.config.CredentialGroup;
-import com.google.enterprise.secmgr.identity.AuthnPrincipal;
-import com.google.enterprise.secmgr.identity.CredPassword;
-import com.google.enterprise.secmgr.identity.Credential;
-import com.google.enterprise.secmgr.identity.GroupMemberships;
-import com.google.enterprise.secmgr.identity.Verification;
-import com.google.enterprise.secmgr.identity.VerificationStatus;
-
-import java.net.URL;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnegative;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.GuardedBy;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * A view of a session snapshot that may be specialized or unspecialized.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public abstract class SessionView {
-
-  @Nonnull protected final SessionSnapshot snapshot;
-  @GuardedBy("this") @Nonnull protected AuthnSessionState.Summary summary;
-
-  protected SessionView(SessionSnapshot snapshot) {
-    Preconditions.checkNotNull(snapshot);
-    this.snapshot = snapshot;
-    summary = null;
-  }
-
-  /**
-   * Creates a session view specialized for a given authentication mechanism.
-   *
-   * @param snapshot The session snapshot the view is a specialization of.
-   * @param mechanism The authentication mechanism to specialize for.
-   * @return A view of the snapshot specialized for the mechanism.
-   */
-  @CheckReturnValue
-  @Nonnull
-  static SessionView create(SessionSnapshot snapshot, AuthnMechanism mechanism) {
-    return new SessionViewForMechanism(snapshot, mechanism);
-  }
-
-  /**
-   * Creates a session view specialized for a given credential group.
-   *
-   * @param snapshot The session snapshot the view is a specialization of.
-   * @param credentialGroup The credential group to specialize for.
-   * @return A view of the snapshot specialized for the credential group.
-   */
-  @CheckReturnValue
-  @Nonnull
-  static SessionView create(SessionSnapshot snapshot, CredentialGroup credentialGroup) {
-    return new SessionViewForCredentialGroup(snapshot, credentialGroup);
-  }
-
-  /**
-   * Creates an unspecialized session view.
-   *
-   * @param snapshot The session snapshot the view is a specialization of.
-   * @return An unspecialized view of the snapshot.
-   */
-  @CheckReturnValue
-  @Nonnull
-  static SessionView create(SessionSnapshot snapshot) {
-    return new SessionViewUnspecialized(snapshot);
-  }
-
-  /**
-   * Gets a new view identical to this one except that it contains the given
-   * user-agent cookies.  Used to update a view after returning from a
-   * credentials gatherer.
-   *
-   * @param userAgentCookies The new user-agent cookies.
-   * @return A new view as specified.
-   */
-  @CheckReturnValue
-  @Nonnull
-  SessionView withNewUserAgentCookies(ImmutableCollection<GCookie> userAgentCookies) {
-    return withNewSnapshot(snapshot.withNewUserAgentCookies(userAgentCookies));
-  }
-
-  @CheckReturnValue
-  @Nonnull
-  protected abstract SessionView withNewSnapshot(SessionSnapshot snapshot);
-
-  /**
-   * Is this a mechanism view?
-   *
-   * @return True only if this view is specialized for an authentication mechanism.
-   */
-  @CheckReturnValue
-  public boolean isSpecializedForMechanism() {
-    return false;
-  }
-
-  /**
-   * Is this a credential-group view?
-   *
-   * @return True only if this view is specialized for a credential group.
-   */
-  @CheckReturnValue
-  public boolean isSpecializedForCredentialGroup() {
-    return false;
-  }
-
-  /**
-   * Is this an unspecialized view?
-   *
-   * @return True only if this is an unspecialized view.
-   */
-  @CheckReturnValue
-  public boolean isUnspecialized() {
-    return false;
-  }
-
-  /**
-   * Gets a summary of the view's session state.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public synchronized AuthnSessionState.Summary getSummary() {
-    if (summary == null) {
-      summary = snapshot.getState().computeSummary(snapshot.getConfig().getCredentialGroups());
-    }
-    return summary;
-  }
-
-  /**
-   * Gets the session ID string.
-   *
-   * @return The session ID string.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public String getSessionId() {
-    return snapshot.getSessionId();
-  }
-
-  /**
-   * Gets the URL that initiated the current authentication request.
-   *
-   * @return The authentication request URL, or null if we're not processing an
-   *     authentication request.
-   */
-  @CheckReturnValue
-  @Nullable
-  public URL getAuthnEntryUrl() {
-    return snapshot.getAuthnEntryUrl();
-  }
-
-  /**
-   * Gets the URL that initiated the current authentication request.
-   *
-   * @return The authentication request URL as a string, or null if we're not
-   *     processing an authentication request.
-   */
-  @CheckReturnValue
-  @Nullable
-  public String getAuthnEntryUrlString() {
-    return getAuthnEntryUrl().toString();
-  }
-
-  /**
-   * Gets the time at which this view's snapshot was taken.
-   *
-   * @return The snapshot time in milliseconds since the epoch.
-   */
-  @CheckReturnValue
-  @Nonnegative
-  public long getTimeStamp() {
-    return snapshot.getTimeStamp();
-  }
-
-  /**
-   * Gets this view's authority, if it is a specialized view.
-   *
-   * @return The authority.
-   * @throws UnsupportedOperationException if this is not a specialized view.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public abstract AuthnAuthority getAuthority();
-
-  /**
-   * Gets this view's credential group, if this is a specialized view.
-   *
-   * @return The credential group.
-   * @throws UnsupportedOperationException if this is not a specialized view.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public abstract CredentialGroup getCredentialGroup();
-
-  /**
-   * Gets this view's mechanism, if this is a mechanism view.
-   *
-   * @return The mechanism associated with this view.
-   * @throws UnsupportedOperationException if this is not a mechanism view.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public abstract AuthnMechanism getMechanism();
-
-  /**
-   * Is this view's credential group required to have a principal?
-   *
-   * @return True if a principal is required.
-   * @throws UnsupportedOperationException if this is not a specialized view.
-   */
-  @CheckReturnValue
-  public boolean getRequiresPrincipal() {
-    return getCredentialGroup().getRequiresUsername();
-  }
-
-  /**
-   * Gets the configured expiration time.
-   *
-   * @return The expiration time.
-   * @throws UnsupportedOperationException if this is not a mechanism view.
-   */
-  @CheckReturnValue
-  public long getConfiguredExpirationTime() {
-    long trustDuration = getMechanism().getTrustDuration();
-    return (trustDuration > 0)
-        ? snapshot.getTimeStamp() + trustDuration
-        : Verification.EXPIRES_AFTER_REQUEST;
-  }
-
-  protected abstract Predicate<AuthnAuthority> getCookieFilter();
-  protected abstract Predicate<AuthnAuthority> getCredentialFilter();
-
-  /**
-   * Is this view satisfied?
-   */
-  @CheckReturnValue
-  public abstract boolean isSatisfied();
-
-  // **************** Cookies ****************
-
-  /**
-   * Gets the cookies that were received from the user agent in the most recent
-   * HTTP request.
-   *
-   * @return The cookies.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public Iterable<GCookie> getUserAgentCookies() {
-    return snapshot.getUserAgentCookies();
-  }
-
-  /**
-   * Gets a user-agent cookie by name.  Note that there can be multiple such
-   * cookies; in that case one is chosen arbitrarily.
-   *
-   * @param name The name of the cookie to get.
-   * @return A cookie with that name, or {@code null} if none.
-   */
-  @CheckReturnValue
-  @Nullable
-  public GCookie getUserAgentCookie(String name) {
-    Preconditions.checkNotNull(name);
-    for (GCookie cookie : getUserAgentCookies()) {
-      if (name.equals(cookie.getName())) {
-        return cookie;
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Gets the cookies that have been received from this view's authorities.
-   *
-   * @return An immutable set of the authority cookies.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public ImmutableSet<GCookie> getAuthorityCookies() {
-    return getSummary().getCookies(getCookieFilter(), getTimeStamp());
-  }
-
-  // **************** Credentials ****************
-
-  /**
-   * Gets the credentials that have been gathered for this view.
-   *
-   * @return An immutable set of the credentials.
-   */
-  public ImmutableSet<Credential> getCredentials() {
-    return getSummary().getCredentials(getCredentialFilter());
-  }
-
-  /**
-   * Gets this view's principal.
-   *
-   * @return The principal, or {@code null} if there isn't one.
-   */
-  @CheckReturnValue
-  @Nullable
-  public AuthnPrincipal getPrincipal() {
-    return getUniqueCredential(AuthnPrincipal.class);
-  }
-
-  /**
-   * Gets this view's password credential.
-   *
-   * @return The password credential, or {@code null} if there isn't one.
-   */
-  @CheckReturnValue
-  @Nullable
-  public CredPassword getPasswordCredential() {
-    return getUniqueCredential(CredPassword.class);
-  }
-
-  /**
-   * Gets this view's group-memberships credential.
-   *
-   * @return The group-memberships credential, or {@code null} if there isn't one.
-   */
-  @CheckReturnValue
-  @Nullable
-  public GroupMemberships getGroupMemberships() {
-    return getUniqueCredential(GroupMemberships.class);
-  }
-
-  private <T extends Credential> T getUniqueCredential(Class<T> clazz) {
-    Credential uniqueCredential = null;
-    for (Credential credential : getCredentials()) {
-      if (clazz.isInstance(credential)) {
-        if (uniqueCredential == null) {
-          uniqueCredential = credential;
-        } else if (!uniqueCredential.equals(credential)) {
-          return null;
-        }
-      }
-    }
-    return clazz.cast(uniqueCredential);
-  }
-
-  /**
-   * Does this view have a principal and a password?
-   *
-   * @return True if the view has exactly one principal and one password.
-   */
-  @CheckReturnValue
-  public boolean hasPrincipalAndPassword() {
-    return hasPrincipalAndPassword(getPrincipal(), getPasswordCredential());
-  }
-
-  private boolean hasPrincipalAndPassword(AuthnPrincipal principal, CredPassword password) {
-    return principal != null
-        && !principal.getName().isEmpty()
-        && password != null
-        && !password.getText().isEmpty();
-  }
-
-  /**
-   * Gets this view's principal and password.
-   *
-   * @return An immutable collection containing those credentials.
-   * @throws IllegalStateException unless both are available.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public ImmutableCollection<Credential> getPrincipalAndPassword() {
-    AuthnPrincipal principal = getPrincipal();
-    CredPassword password = getPasswordCredential();
-    Preconditions.checkState(hasPrincipalAndPassword(principal, password));
-    return ImmutableList.<Credential>of(principal, password);
-  }
-
-  /**
-   * Gets this view's username.
-   *
-   * @return The username, or {@code null} if there isn't one.
-   */
-  @CheckReturnValue
-  @Nullable
-  public String getUsername() {
-    AuthnPrincipal principal = getPrincipal();
-    return (principal != null) ? principal.getName() : null;
-  }
-
-  /**
-   * Gets this view's domain.
-   *
-   * @return The domain, or {@code null} if there isn't one.
-   */
-  @CheckReturnValue
-  @Nullable
-  public String getDomain() {
-    AuthnPrincipal principal = getPrincipal();
-    return (principal != null) ? principal.getActiveDirectoryDomain() : null;
-  }
-
-  /**
-   * Gets this view's password.
-   *
-   * @return The password, or {@code null} if there isn't one.
-   */
-  @CheckReturnValue
-  @Nullable
-  public String getPassword() {
-    CredPassword password = getPasswordCredential();
-    return (password != null) ? password.getText() : null;
-  }
-
-  /**
-   * Gets this view's groups.
-   *
-   * @return The groups, as an immutable set.
-   */
-  @CheckReturnValue
-  @Nullable
-  public ImmutableSet<String> getGroups() {
-    GroupMemberships groups = getGroupMemberships();
-    return (groups != null) ? groups.getGroups() : ImmutableSet.<String>of();
-  }
-
-  // **************** Verifications ****************
-
-  /**
-   * Gets the verifications for this view.
-   *
-   * @return An immutable set of this view's verifications.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public ImmutableSet<Verification> getVerifications() {
-    return getSummary().getVerifications(getCredentialFilter(), getTimeStamp());
-  }
-
-  /**
-   * Does this view have a verified principal?
-   *
-   * @return True if this view has at least one verification containing a
-   *     principal, and if no other verification contains a different principal.
-   */
-  @CheckReturnValue
-  public boolean hasVerifiedPrincipal() {
-    return null != getUniqueVerifiedCredential(AuthnPrincipal.class);
-  }
-
-  /**
-   * Does this view have a verified password?
-   *
-   * @return True if this view has at least one verification containing a
-   *     password, and if no other verification contains a different password.
-   */
-  @CheckReturnValue
-  protected boolean hasVerifiedPassword() {
-    return null != getUniqueVerifiedCredential(AuthnPrincipal.class);
-  }
-
-  /**
-   * Does this view have a jointly verified principal and password?
-   *
-   * @return True if this view has at least one verification containing both a
-   *     principal and password, and if no other verification contains a
-   *     different principal or password.
-   */
-  @CheckReturnValue
-  public boolean hasVerifiedPrincipalAndPassword() {
-    AuthnPrincipal principal = getUniqueVerifiedCredential(AuthnPrincipal.class);
-    CredPassword password = getUniqueVerifiedCredential(CredPassword.class);
-    return principal != null
-        && password != null
-        && areJointlyVerified(principal, password);
-  }
-
-  /**
-   * Gets a verified principal.
-   *
-   * @return The verified principal.  Returns {@code null} if
-   *     {@code hasVerifiedPrincipal()} is false.
-   */
-  @CheckReturnValue
-  @Nullable
-  public AuthnPrincipal getVerifiedPrincipal() {
-    return getUniqueVerifiedCredential(AuthnPrincipal.class);
-  }
-
-  /**
-   * Gets the verified groups for this view.
-   *
-   * @return The verified groups, may be empty.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public ImmutableSet<String> getVerifiedGroups() {
-    ImmutableSet.Builder<String> builder = ImmutableSet.builder();
-    for (GroupMemberships credential : getVerifiedCredentials(GroupMemberships.class)) {
-      builder.addAll(credential.getGroups());
-    }
-    return builder.build();
-  }
-
-  /**
-   * Gets the expiration time of a credential.
-   *
-   * @param credential A credential to get the expiration time for.
-   * @return The credential's expiration time, or {@code 0} if the credential
-   *     isn't verified.
-   */
-  @CheckReturnValue
-  public long getCredentialExpirationTime(Credential credential) {
-    Preconditions.checkNotNull(credential);
-    return Verification.maximumExpirationTime(getJointVerifications(credential));
-  }
-
-  private <T extends Credential> T getUniqueVerifiedCredential(Class<T> clazz) {
-    Credential uniqueCredential = null;
-    for (Verification verification : getVerifications()) {
-      if (verification.isVerified()) {
-        for (Credential credential : verification.getCredentials()) {
-          if (clazz.isInstance(credential)) {
-            if (uniqueCredential == null) {
-              uniqueCredential = credential;
-            } else if (!uniqueCredential.equals(credential)) {
-              return null;
-            }
-          }
-        }
-      }
-    }
-    return clazz.cast(uniqueCredential);
-  }
-
-  private <T extends Credential> Iterable<T> getVerifiedCredentials(Class<T> clazz) {
-    ImmutableList.Builder<T> builder = ImmutableList.builder();
-    for (Verification verification : getVerifications()) {
-      if (verification.isVerified()) {
-        for (Credential credential : verification.getCredentials()) {
-          if (clazz.isInstance(credential)) {
-            builder.add(clazz.cast(credential));
-          }
-        }
-      }
-    }
-    return builder.build();
-  }
-
-  private boolean areJointlyVerified(Credential... credentials) {
-    return Iterables.any(getVerifications(),
-        Predicates.and(
-            Verification.isVerifiedPredicate(),
-            Verification.getContainsAllCredentialsPredicate(credentials)));
-  }
-
-  private Iterable<Verification> getJointVerifications(Credential... credentials) {
-    return Iterables.filter(getVerifications(),
-        Predicates.and(
-            Verification.isVerifiedPredicate(),
-            Verification.getContainsAllCredentialsPredicate(credentials)));
-  }
-
-  /**
-   * Gets this view's verification status.
-   *
-   * @return The verification status.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public VerificationStatus getVerificationStatus() {
-    return Verification.getStatus(getVerifications());
-  }
-
-  /**
-   * Does this view have no refutations and at least one verification?
-   *
-   * @return True if this view is verified.
-   */
-  @CheckReturnValue
-  public boolean isVerified() {
-    return getVerificationStatus() == VerificationStatus.VERIFIED;
-  }
-
-  /**
-   * Does this view have at least one refutation?
-   *
-   * @return True if this view is refuted.
-   */
-  @CheckReturnValue
-  public boolean isRefuted() {
-    return getVerificationStatus() == VerificationStatus.REFUTED;
-  }
-
-  /**
-   * Does this view have no refutations and no verifications?
-   *
-   * @return True if this view is indeterminate.
-   */
-  @CheckReturnValue
-  public boolean isIndeterminate() {
-    return getVerificationStatus() == VerificationStatus.INDETERMINATE;
-  }
-
-  // **************** Logging ****************
-
-  /**
-   * Annotates a log message with this view's session ID.
-   *
-   * @param format The format string to pass to {@link String#format}.
-   * @param args The arguments to pass to {@link String#format}.
-   * @return The annotated log message.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public String logMessage(String format, Object... args) {
-    return snapshot.logMessage(format, args);
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/authncontroller/SessionViewForCredentialGroup.java b/src/com/google/enterprise/secmgr/authncontroller/SessionViewForCredentialGroup.java
deleted file mode 100644
index bf427c4..0000000
--- a/src/com/google/enterprise/secmgr/authncontroller/SessionViewForCredentialGroup.java
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.secmgr.authncontroller;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.enterprise.secmgr.config.AuthnAuthority;
-import com.google.enterprise.secmgr.config.AuthnMechanism;
-import com.google.enterprise.secmgr.config.CredentialGroup;
-import com.google.enterprise.secmgr.identity.AuthnPrincipal;
-import com.google.enterprise.secmgr.identity.CredPassword;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * A view of a session snapshot that's specialized for a credential group.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-final class SessionViewForCredentialGroup extends SessionView {
-
-  @Nonnull private final CredentialGroup credentialGroup;
-
-  SessionViewForCredentialGroup(SessionSnapshot snapshot, CredentialGroup credentialGroup) {
-    super(snapshot);
-    Preconditions.checkNotNull(credentialGroup);
-    Preconditions.checkState(
-        snapshot.getConfig().getCredentialGroups().contains(credentialGroup));
-    this.credentialGroup = credentialGroup;
-  }
-
-  @Override
-  protected SessionView withNewSnapshot(SessionSnapshot snapshot) {
-    return snapshot.getView(credentialGroup);
-  }
-
-  @Override
-  public boolean isSpecializedForCredentialGroup() {
-    return true;
-  }
-
-  @Override
-  public AuthnAuthority getAuthority() {
-    return credentialGroup.getAuthority();
-  }
-
-  @Override
-  public AuthnMechanism getMechanism() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public CredentialGroup getCredentialGroup() {
-    return credentialGroup;
-  }
-
-  @Override
-  protected Predicate<AuthnAuthority> getCookieFilter() {
-    return snapshot.getConfig().getAuthorityPredicate(credentialGroup);
-  }
-
-  @Override
-  protected Predicate<AuthnAuthority> getCredentialFilter() {
-    return snapshot.getConfig().getAuthorityPredicate(credentialGroup);
-  }
-
-  @Override
-  public boolean isSatisfied() {
-    if (credentialGroup.getMechanisms().isEmpty()) {
-      // An empty group is never satisfied.
-      logMessage("Credential group %s not satisfied because it is empty.",
-          credentialGroup.getName());
-      return false;
-    }
-
-    if (isRefuted()) {
-      logMessage("Credential group %s not satisfied because it is refuted.",
-          credentialGroup.getName());
-      return false;
-    }
-
-    // If principal is required, it must be present and non-empty.
-    if (credentialGroup.getRequiresUsername() && !hasVerifiedPrincipal()) {
-      logMessage("Credential group %s not satisfied because it requires a username.",
-          credentialGroup.getName());
-      return false;
-    }
-
-    // If password is required, it must be present and non-empty.
-    if (credentialGroup.getRequiresPassword() && !hasVerifiedPassword()) {
-      logMessage("Credential group %s not satisfied because it requires a password.",
-          credentialGroup.getName());
-      return false;
-    }
-
-    // If group is optional, empty principal and password are sufficient.
-    // Note that both the principal and the password must be present; otherwise
-    // that means we haven't yet gathered credentials, so we must not return
-    // satisfied.  When they are both empty, it means we gathered credentials
-    // and the user didn't fill them in.
-    if (credentialGroup.getIsOptional() && hasEmptyPrincipal() && hasEmptyPassword()) {
-      logMessage("Credential group %s satisfied because it's optional and was left blank.",
-          credentialGroup.getName());
-      return true;
-    }
-
-    // TODO(cph): This doesn't check the credentials -- so the username and/or
-    // password might not be verified.  Unfortunately, the program's current
-    // logic doesn't understand that credentials must be verified independently
-    // of the satisfaction of their identity group.
-    return isVerified();
-  }
-
-  private boolean hasEmptyPrincipal() {
-    AuthnPrincipal principal = getPrincipal();
-    return principal != null && principal.getName().isEmpty();
-  }
-
-  private boolean hasEmptyPassword() {
-    CredPassword password = getPasswordCredential();
-    return password != null && password.getText().isEmpty();
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder builder = new StringBuilder();
-    builder.append("{SessionView of ");
-    builder.append(snapshot);
-    builder.append(" specialized for: ");
-    builder.append(credentialGroup);
-    builder.append("}");
-    return builder.toString();
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/authncontroller/SessionViewForMechanism.java b/src/com/google/enterprise/secmgr/authncontroller/SessionViewForMechanism.java
deleted file mode 100644
index a3acde1..0000000
--- a/src/com/google/enterprise/secmgr/authncontroller/SessionViewForMechanism.java
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.secmgr.authncontroller;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.enterprise.secmgr.config.AuthnAuthority;
-import com.google.enterprise.secmgr.config.AuthnMechanism;
-import com.google.enterprise.secmgr.config.CredentialGroup;
-import com.google.enterprise.secmgr.identity.Verification;
-import com.google.enterprise.secmgr.identity.VerificationStatus;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * A view of a session snapshot that's specialized for an authority.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-final class SessionViewForMechanism extends SessionView {
-  @Nonnull private final AuthnMechanism mechanism;
-  @Nonnull private final CredentialGroup credentialGroup;
-
-  SessionViewForMechanism(SessionSnapshot snapshot, AuthnMechanism mechanism) {
-    super(snapshot);
-    Preconditions.checkNotNull(mechanism);
-    this.mechanism = mechanism;
-    credentialGroup = snapshot.getConfig().getCredentialGroup(mechanism);
-  }
-
-  @Override
-  protected SessionView withNewSnapshot(SessionSnapshot snapshot) {
-    return snapshot.getView(mechanism);
-  }
-
-  @Override
-  public boolean isSpecializedForMechanism() {
-    return true;
-  }
-
-  @Override
-  public AuthnAuthority getAuthority() {
-    return mechanism.getAuthority();
-  }
-
-  @Override
-  public CredentialGroup getCredentialGroup() {
-    return credentialGroup;
-  }
-
-  @Override
-  public AuthnMechanism getMechanism() {
-    return mechanism;
-  }
-
-  @Override
-  protected Predicate<AuthnAuthority> getCookieFilter() {
-    return Predicates.equalTo(getAuthority());
-  }
-
-  @Override
-  protected Predicate<AuthnAuthority> getCredentialFilter() {
-    return snapshot.getConfig().getAuthorityPredicate(credentialGroup);
-  }
-
-  @Override
-  public VerificationStatus getVerificationStatus() {
-    return Verification.getStatus(
-        getSummary().getVerifications(Predicates.equalTo(getAuthority()), getTimeStamp()));
-  }
-
-  @Override
-  public boolean isSatisfied() {
-    return isVerified();
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder builder = new StringBuilder();
-    builder.append("{SessionView of ");
-    builder.append(snapshot);
-    builder.append(" specialized for: ");
-    builder.append(mechanism);
-    builder.append("}");
-    return builder.toString();
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/authncontroller/SessionViewUnspecialized.java b/src/com/google/enterprise/secmgr/authncontroller/SessionViewUnspecialized.java
deleted file mode 100644
index 063ab9f..0000000
--- a/src/com/google/enterprise/secmgr/authncontroller/SessionViewUnspecialized.java
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.secmgr.authncontroller;
-
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.Lists;
-import com.google.enterprise.secmgr.config.AuthnAuthority;
-import com.google.enterprise.secmgr.config.AuthnMechanism;
-import com.google.enterprise.secmgr.config.CredentialGroup;
-
-import java.util.List;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * A view of a session snapshot that's not specialized.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-final class SessionViewUnspecialized extends SessionView {
-
-  SessionViewUnspecialized(final SessionSnapshot snapshot) {
-    super(snapshot);
-  }
-
-  @Override
-  protected SessionView withNewSnapshot(SessionSnapshot snapshot) {
-    return snapshot.getView();
-  }
-
-  @Override
-  public boolean isUnspecialized() {
-    return true;
-  }
-
-  @Override
-  public AuthnAuthority getAuthority() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public CredentialGroup getCredentialGroup() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public AuthnMechanism getMechanism() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  protected Predicate<AuthnAuthority> getCookieFilter() {
-    return Predicates.alwaysTrue();
-  }
-
-  @Override
-  protected Predicate<AuthnAuthority> getCredentialFilter() {
-    return Predicates.alwaysTrue();
-  }
-
-  @Override
-  public boolean isSatisfied() {
-    List<CredentialGroup> nonEmpty = Lists.newArrayList();
-    for (CredentialGroup credentialGroup : snapshot.getConfig().getCredentialGroups()) {
-      if (!credentialGroup.getMechanisms().isEmpty()) {
-        nonEmpty.add(credentialGroup);
-      }
-    }
-    if (nonEmpty.isEmpty()) {
-      logMessage("No non-empty credential groups, so nothing to be satisfied.");
-      return false;
-    }
-    for (CredentialGroup credentialGroup : nonEmpty) {
-      if (!snapshot.getView(credentialGroup).isSatisfied()) {
-        logMessage("Credential group %s reports not satisfied, so session is not satisfied.",
-            credentialGroup.getName());
-        return false;
-      }
-    }
-    return true;
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder builder = new StringBuilder();
-    builder.append("{SessionView of ");
-    builder.append(snapshot);
-    builder.append("}");
-    return builder.toString();
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/common/Base64.java b/src/com/google/enterprise/secmgr/common/Base64.java
deleted file mode 100644
index fa88ccd..0000000
--- a/src/com/google/enterprise/secmgr/common/Base64.java
+++ /dev/null
@@ -1,477 +0,0 @@
-// Copyright 2002 Google Inc.
-//
-// 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.
-
-// This code was converted from code at http://iharder.sourceforge.net/base64/
-// Lots of extraneous features were removed.
-/* The original code said:
- * <p>
- * I am placing this code in the Public Domain. Do with it as you will.
- * This software comes with no guarantees or warranties but with
- * plenty of well-wishing instead!
- * Please visit
- * <a href="http://iharder.net/xmlizable">http://iharder.net/xmlizable</a>
- * periodically to check for updates or to contribute improvements.
- * </p>
- *
- * @author Robert Harder
- * @author rharder@usa.net
- * @version 1.3
- */
-
-package com.google.enterprise.secmgr.common;
-
-/**
- * Base64 converter class. This code is not a full-blown MIME encoder;
- * it simply converts binary data to base64 data and back.
- */
-public class Base64 {
-  /** Specify encoding (value is {@code true}). */
-  public static final boolean ENCODE = true;
-
-  /** Specify decoding (value is {@code false}). */
-  public static final boolean DECODE = false;
-
-  /** The equals sign (=) as a byte. */
-  private static final byte EQUALS_SIGN = (byte) '=';
-
-  /** The new line character (\n) as a byte. */
-  private static final byte NEW_LINE = (byte) '\n';
-
-  /** The 64 valid Base64 values. */
-  public static final byte[] ALPHABET =
-      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
-      .getBytes();
-
-  /** The 64 valid web safe Base64 values. */
-  public static final byte[] WEBSAFE_ALPHABET =
-      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
-      .getBytes();
-
-  /**
-   * Translates a Base64 value to either its 6-bit reconstruction value
-   * or a negative number indicating some other meaning.  This can decode
-   * content that was endoded with either the standard ALPHABET or the
-   * WEBSAFE_ALPHABET.
-   */
-  private static final byte[] DECODABET = {
-      -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal  0 -  8
-      -5, -5, // Whitespace: Tab and Linefeed
-      -9, -9, // Decimal 11 - 12
-      -5, // Whitespace: Carriage Return
-      -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
-      -9, -9, -9, -9, -9, // Decimal 27 - 31
-      -5, // Whitespace: Space
-      -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
-      62, // Plus sign at decimal 43
-      -9, // Decimal 44
-      62, // Dash '-' sign at decimal 45 (from WebSafe encoding)
-      -9, // Decimal 46
-      63, // Slash at decimal 47
-      52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
-      -9, -9, -9, // Decimal 58 - 60
-      -1, // Equals sign at decimal 61
-      -9, -9, -9, // Decimal 62 - 64
-      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'
-      14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
-      -9, -9, -9, -9, // Decimal 91-94
-      63, // Underscore '_' at decimal 95 (from WebSafe encoding)
-      -9, // Decimal 96
-      26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'
-      39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'
-      -9, -9, -9, -9, -9 // Decimal 123 - 127
-  };
-
-  // Indicates white space in encoding.
-  private static final byte WHITE_SPACE_ENC = -5;
-
-  // Indicates equals sign in encoding.
-  private static final byte EQUALS_SIGN_ENC = -1;
-
-  private Base64() {
-    // Defeats instantiation.
-  }
-
-  /* ********  E N C O D I N G   M E T H O D S  ******** */
-
-  /**
-   * Encodes up to three bytes of the array <var>source</var>
-   * and writes the resulting four Base64 bytes to <var>destination</var>.
-   * The source and destination arrays can be manipulated
-   * anywhere along their length by specifying
-   * <var>srcOffset</var> and <var>destOffset</var>.
-   * This method does not check to make sure your arrays
-   * are large enough to accommodate <var>srcOffset</var> + 3 for
-   * the <var>source</var> array or <var>destOffset</var> + 4 for
-   * the <var>destination</var> array.
-   * The actual number of significant bytes in your array is
-   * given by <var>numSigBytes</var>.
-   *
-   * @param source the array to convert
-   * @param srcOffset the index where conversion begins
-   * @param numSigBytes the number of significant bytes in your array
-   * @param destination the array to hold the conversion
-   * @param destOffset the index where output will be put
-   * @param alphabet is the encoding alphabet
-   * @return the <var>destination</var> array
-   * @since 1.3
-   */
-  static byte[] encode3to4(byte[] source, int srcOffset,
-      int numSigBytes, byte[] destination, int destOffset, byte[] alphabet) {
-    //           1         2         3
-    // 01234567890123456789012345678901 Bit position
-    // --------000000001111111122222222 Array position from threeBytes
-    // --------|    ||    ||    ||    | Six bit groups to index alphabet
-    //          >>18  >>12  >> 6  >> 0  Right shift necessary
-    //                0x3f  0x3f  0x3f  Additional AND
-
-    // Create buffer with zero-padding if there are only one or two
-    // significant bytes passed in the array.
-    // We have to shift left 24 in order to flush out the 1's that appear
-    // when Java treats a value as negative that is cast from a byte to an int.
-    int inBuff =
-        (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0)
-        | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)
-        | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);
-
-    switch (numSigBytes) {
-      case 3:
-        destination[destOffset] = alphabet[(inBuff >>> 18)];
-        destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f];
-        destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f];
-        destination[destOffset + 3] = alphabet[(inBuff) & 0x3f];
-        return destination;
-      case 2:
-        destination[destOffset] = alphabet[(inBuff >>> 18)];
-        destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f];
-        destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f];
-        destination[destOffset + 3] = EQUALS_SIGN;
-        return destination;
-      case 1:
-        destination[destOffset] = alphabet[(inBuff >>> 18)];
-        destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f];
-        destination[destOffset + 2] = EQUALS_SIGN;
-        destination[destOffset + 3] = EQUALS_SIGN;
-        return destination;
-      default:
-        return destination;
-    } // end switch
-  } // end encode3to4
-
-  /**
-   * Encodes a byte array into Base64 notation.
-   * Equivalent to calling
-   * {@code encodeBytes(source, 0, source.length)}
-   *
-   * @param source The data to convert
-   * @since 1.4
-   */
-  public static String encode(byte[] source) {
-    return encode(source, 0, source.length, ALPHABET, true);
-  }
-
-  /**
-   * Encodes a byte array into web safe Base64 notation.
-   *
-   * @param source The data to convert
-   * @param doPadding is {@code true} to pad result with '=' chars
-   *        if it does not fall on 3 byte boundaries
-   */
-  public static String encodeWebSafe(byte[] source, boolean doPadding) {
-    return encode(source, 0, source.length, WEBSAFE_ALPHABET, doPadding);
-  }
-
-  /**
-   * Encodes a byte array into Base64 notation.
-   *
-   * @param source The data to convert
-   * @param off Offset in array where conversion should begin
-   * @param len Length of data to convert
-   * @param alphabet is the encoding alphabet
-   * @param doPadding is {@code true} to pad result with '=' chars
-   *        if it does not fall on 3 byte boundaries
-   * @since 1.4
-   */
-  public static String encode(byte[] source, int off, int len, byte[] alphabet,
-      boolean doPadding) {
-    byte[] outBuff = encode(source, off, len, alphabet, Integer.MAX_VALUE);
-    int outLen = outBuff.length;
-
-    // If doPadding is false, set length to truncate '='
-    // padding characters
-    while (doPadding == false && outLen > 0) {
-      if (outBuff[outLen - 1] != '=') {
-        break;
-      }
-      outLen -= 1;
-    }
-
-    return new String(outBuff, 0, outLen);
-  }
-
-  /**
-   * Encodes a byte array into Base64 notation.
-   *
-   * @param source The data to convert
-   * @param off Offset in array where conversion should begin
-   * @param len Length of data to convert
-   * @param alphabet is the encoding alphabet
-   * @param maxLineLength maximum length of one line.
-   * @return the BASE64-encoded byte array
-   */
-  public static byte[] encode(byte[] source, int off, int len, byte[] alphabet,
-      int maxLineLength) {
-    int len43 = ((len + 2) / 3) * 4;
-    byte[] outBuff = new byte[len43 + (len43 / maxLineLength)];
-
-    encode(source, off, len, outBuff, 0, alphabet, maxLineLength);
-    return outBuff;
-  }
-
-  /**
-   * Encodes a byte array into Base64 notation into a destination byte array.
-   * Warning: No check is made to make sure the destination is big enough
-   * to hold the conversion.
-   * This was optimally constructed for use by Base64FilterInputStream.
-   *
-   * @param source The data to convert
-   * @param sourceOffset Offset in source array where conversion should begin
-   * @param sourceLength Length of data to convert
-   * @param dest The destination array for converted data
-   * @param destOffset Offset in destination array to write
-   * @param alphabet is the encoding alphabet
-   * @param maxLineLength maximum length of one line.
-   * @return the number of bytes written to destination.
-   */
-  static int encode(byte[] source, int sourceOffset, int sourceLength,
-      byte[] dest, int destOffset, byte[] alphabet, int maxLineLength) {
-    int s = 0;
-    int d = destOffset;
-    int len = sourceLength - 2;
-    int lineLength = 0;
-
-    for (; s < len; s += 3, d += 4) {
-      // The following block of code is the same as
-      // encode3to4( source, s + off, 3, dest, d, alphabet );
-      // but inlined for faster encoding (~20% improvement)
-      int inBuff =
-          ((source[s + sourceOffset] << 24) >>> 8)
-          | ((source[s + 1 + sourceOffset] << 24) >>> 16)
-          | ((source[s + 2 + sourceOffset] << 24) >>> 24);
-      dest[d] = alphabet[(inBuff >>> 18)];
-      dest[d + 1] = alphabet[(inBuff >>> 12) & 0x3f];
-      dest[d + 2] = alphabet[(inBuff >>> 6) & 0x3f];
-      dest[d + 3] = alphabet[(inBuff) & 0x3f];
-
-      if ((lineLength += 4) >= maxLineLength) {
-        dest[d + 4] = NEW_LINE;
-        d++;
-        lineLength = 0;
-      } // end if: end of line
-    } // end for: each piece of array
-
-    if (s < sourceLength) {
-      encode3to4(source, s + sourceOffset, sourceLength - s, dest, d, alphabet);
-      d += 4;
-      if ((lineLength += 4) >= maxLineLength) {
-        dest[d++] = NEW_LINE;
-      }
-    }
-
-    return d - destOffset;
-  }
-
-  /* ********  D E C O D I N G   M E T H O D S  ******** */
-
-  /**
-   * Decodes four bytes from array <var>source</var>
-   * and writes the resulting bytes (up to three of them)
-   * to <var>destination</var>.
-   * The source and destination arrays can be manipulated
-   * anywhere along their length by specifying
-   * <var>srcOffset</var> and <var>destOffset</var>.
-   * This method does not check to make sure your arrays
-   * are large enough to accommodate <var>srcOffset</var> + 4 for
-   * the <var>source</var> array or <var>destOffset</var> + 3 for
-   * the <var>destination</var> array.
-   * This method returns the actual number of bytes that
-   * were converted from the Base64 encoding.
-   *
-   *
-   * @param source the array to convert
-   * @param srcOffset the index where conversion begins
-   * @param destination the array to hold the conversion
-   * @param destOffset the index where output will be put
-   * @param decodabet the decodabet for decoding Base64 content
-   * @return the number of decoded bytes converted
-   * @since 1.3
-   */
-  private static int decode4to3(byte[] source, int srcOffset,
-      byte[] destination, int destOffset, byte[] decodabet) {
-    // Example: Dk==
-    if (source[srcOffset + 2] == EQUALS_SIGN) {
-      int outBuff =
-          ((decodabet[source[srcOffset]] << 24) >>> 6)
-          | ((decodabet[source[srcOffset + 1]] << 24) >>> 12);
-
-      destination[destOffset] = (byte) (outBuff >>> 16);
-      return 1;
-    } else if (source[srcOffset + 3] == EQUALS_SIGN) {
-      // Example: DkL=
-      int outBuff =
-          ((decodabet[source[srcOffset]] << 24) >>> 6)
-          | ((decodabet[source[srcOffset + 1]] << 24) >>> 12)
-          | ((decodabet[source[srcOffset + 2]] << 24) >>> 18);
-
-      destination[destOffset] = (byte) (outBuff >>> 16);
-      destination[destOffset + 1] = (byte) (outBuff >>> 8);
-      return 2;
-    } else {
-      // Example: DkLE
-      int outBuff =
-          ((decodabet[source[srcOffset]] << 24) >>> 6)
-          | ((decodabet[source[srcOffset + 1]] << 24) >>> 12)
-          | ((decodabet[source[srcOffset + 2]] << 24) >>> 18)
-          | ((decodabet[source[srcOffset + 3]] << 24) >>> 24);
-
-      destination[destOffset] = (byte) (outBuff >> 16);
-      destination[destOffset + 1] = (byte) (outBuff >> 8);
-      destination[destOffset + 2] = (byte) (outBuff);
-      return 3;
-    }
-  } // end decodeToBytes
-
-  /**
-   * Decodes data from Base64 notation.
-   * Understands either standard or web-safe encoding.
-   *
-   * @param s the string to decode (decoded in default encoding)
-   * @return the decoded data
-   * @since 1.4
-   */
-  public static byte[] decode(String s) throws Base64DecoderException {
-    byte[] bytes = s.getBytes();
-    return decode(bytes, 0, bytes.length, DECODABET);
-  }
-
-  /**
-   * Decodes Base64 content in byte array format and returns
-   * the decoded byte array.
-   * Understands either standard or web-safe encoding.
-   *
-   * @param source The Base64 encoded data
-   * @return decoded data
-   * @since 1.3
-   * @throws Base64DecoderException
-   */
-  public static byte[] decode(byte[] source) throws Base64DecoderException {
-    return decode(source, 0, source.length, DECODABET);
-  }
-
-  /**
-   * Decodes Base64 content in byte array format and returns
-   * the decoded byte array.
-   * Understands either standard or web-safe encoding.
-   *
-   * @param source The Base64 encoded data
-   * @param off    The offset of where to begin decoding
-   * @param len    The length of characters to decode
-   * @return decoded data
-   * @since 1.3
-   * @throws Base64DecoderException
-   */
-  public static byte[] decode(byte[] source, int off, int len)
-      throws Base64DecoderException {
-    return decode(source, off, len, DECODABET);
-  }
-
-  /**
-   * Decodes Base64 content using the supplied decodabet and returns
-   * the decoded byte array.
-   * Understands either standard or web-safe encoding.
-   *
-   * @param source    The Base64 encoded data
-   * @param off       The offset of where to begin decoding
-   * @param len       The length of characters to decode
-   * @param decodabet the decodabet for decoding Base64 content
-   * @return decoded data
-   */
-  public static byte[] decode(byte[] source, int off, int len, byte[] decodabet)
-      throws Base64DecoderException {
-    int len34 = len * 3 / 4;
-    byte[] outBuff = new byte[2 + len34]; // Upper limit on size of output
-    int outBuffPosn = 0;
-
-    byte[] b4 = new byte[4];
-    int b4Posn = 0;
-    int i = 0;
-    byte sbiCrop = 0;
-    byte sbiDecode = 0;
-    for (i = 0; i < len; i++) {
-      sbiCrop = (byte) (source[i + off] & 0x7f); // Only the low seven bits
-      sbiDecode = decodabet[sbiCrop];
-
-      if (sbiDecode >= WHITE_SPACE_ENC) { // White space Equals sign or better
-        if (sbiDecode >= EQUALS_SIGN_ENC) {
-          // An equals sign (for padding) must not occur at position 0 or 1
-          // and must be the last byte[s] in the encoded value.
-          if (sbiCrop == EQUALS_SIGN) {
-            int bytesLeft = len - i;
-            byte lastByte = (byte) (source[len - 1 + off] & 0x7f);
-            if (b4Posn == 0 || b4Posn == 1) {
-              throw new Base64DecoderException(
-                  "invalid padding byte '=' at byte offset " + i);
-            } else if ((b4Posn == 3 && bytesLeft > 2)
-                || (b4Posn == 4 && bytesLeft > 1)) {
-              throw new Base64DecoderException(
-                  "padding byte '=' falsely signals end of encoded value "
-                  + "at offset " + i);
-            } else if (lastByte != EQUALS_SIGN && lastByte != NEW_LINE) {
-              throw new Base64DecoderException(
-                  "encoded value has invalid trailing byte");
-            }
-            break;
-          }
-
-          b4[b4Posn++] = sbiCrop;
-          if (b4Posn == 4) {
-            outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet);
-            b4Posn = 0;
-          }
-        }
-      } else {
-        throw new Base64DecoderException("Bad Base64 input character at " + i
-            + ": " + source[i + off] + "(decimal)");
-      }
-    }
-
-    // Because web safe encoding allows non padding base64 encodes, we
-    // need to pad the rest of the b4 buffer with equal signs when
-    // b4Posn != 0.  There can be at most 2 equal signs at the end of
-    // four characters, so the b4 buffer must have two or three
-    // characters.  This also catches the case where the input is
-    // padded with EQUALS_SIGN.
-    if (b4Posn != 0) {
-      if (b4Posn == 1) {
-        throw new Base64DecoderException("single trailing character at offset "
-            + (len - 1));
-      }
-      b4[b4Posn++] = EQUALS_SIGN;
-      outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet);
-    }
-
-    byte[] out = new byte[outBuffPosn];
-    System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
-    return out;
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/common/Base64DecoderException.java b/src/com/google/enterprise/secmgr/common/Base64DecoderException.java
deleted file mode 100644
index 39ac218..0000000
--- a/src/com/google/enterprise/secmgr/common/Base64DecoderException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2002 Google Inc.
-//
-// 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.secmgr.common;
-
-/**
- * Exception thrown when encountering an invalid Base64 input character.
- *
- * <p>This class may be used with the Google Web Toolkit (GWT).
- */
-public class Base64DecoderException extends Exception {
-  public Base64DecoderException() {
-    super();
-  }
-
-  public Base64DecoderException(String s) {
-    super(s);
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/common/Chain.java b/src/com/google/enterprise/secmgr/common/Chain.java
deleted file mode 100644
index 064119e..0000000
--- a/src/com/google/enterprise/secmgr/common/Chain.java
+++ /dev/null
@@ -1,428 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.secmgr.common;
-
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnegative;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-import javax.annotation.concurrent.NotThreadSafe;
-
-/**
- * An immutable accumulator that adds elements to the end of a "chain" and can
- * later convert that to a {@link List}.
- *
- * @param <E> The type of the elements stored in this chain.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public abstract class Chain<E> implements Iterable<E> {
-
-  @Nonnull private static final Chain<?> EMPTY_CHAIN = new EmptyChain<Object>();
-
-  /**
-   * Gets a new chain with no elements.
-   */
-  @CheckReturnValue
-  @SuppressWarnings("unchecked")
-  @Nonnull
-  public static <F> Chain<F> empty() {
-    return (Chain<F>) EMPTY_CHAIN;
-  }
-
-  /**
-   * Gets a new chain with the given elements.
-   *
-   * @param elements The elements to make a chain from.
-   * @return A chain of those elements.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static <F> Chain<F> copyOf(Iterable<F> elements) {
-    Chain<F> chain = empty();
-    for (F element : elements) {
-      chain = chain.add(element);
-    }
-    return chain;
-  }
-
-  /**
-   * Gets the number of elements in this chain.
-   *
-   * @return The number of elements.
-   */
-  @CheckReturnValue
-  @Nonnegative
-  public abstract int size();
-
-  /**
-   * Is this an empty chain?
-   *
-   * @return True if this chain has no elements.
-   */
-  @CheckReturnValue
-  public abstract boolean isEmpty();
-
-  /**
-   * Gets the last element in this chain.  That is, for any chain {@code C} and
-   * element {@code E}, {@code C.add(E).getLast() == E}.
-   *
-   * @return The last element in the chain.
-   * @throws UnsupportedOperationException if this is an empty chain.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public abstract E getLast();
-
-  /**
-   * Gets the rest of this chain.  That is, for any chain {@code C} and element
-   * {@code E}, {@code C.add(E).getRest() == C}.
-   *
-   * @return The rest of this chain.
-   * @throws UnsupportedOperationException if this is an empty chain.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public abstract Chain<E> getRest();
-
-  @Immutable
-  private static final class EmptyChain<F> extends Chain<F> {
-    @Override
-    public int size() {
-      return 0;
-    }
-
-    @Override
-    public boolean isEmpty() {
-      return true;
-    }
-
-    @Override
-    public F getLast() {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public Chain<F> getRest() {
-      throw new UnsupportedOperationException();
-    }
-  }
-
-  @Immutable
-  @ParametersAreNonnullByDefault
-  private static final class NonEmptyChain<F> extends Chain<F> {
-    @Nonnegative final int numberOfElements;
-    @Nullable final F element;
-    @Nonnull final Chain<F> rest;
-
-    NonEmptyChain(@Nullable F element, Chain<F> rest) {
-      Preconditions.checkNotNull(rest);
-      this.numberOfElements = rest.size() + 1;
-      this.element = element;
-      this.rest = rest;
-    }
-
-    @Override
-    public int size() {
-      return numberOfElements;
-    }
-
-    @Override
-    public boolean isEmpty() {
-      return false;
-    }
-
-    @Override
-    @Nullable
-    public F getLast() {
-      return element;
-    }
-
-    @Override
-    @Nonnull
-    public Chain<F> getRest() {
-      return rest;
-    }
-  }
-
-  /**
-   * Adds a new element to the chain.  Since this is an immutable structure, a
-   * new chain is returned that contains the new element as well as all the
-   * elements of this chain.  The new chain has a "last" of {@code element} and
-   * a "rest" of {@code this}.
-   *
-   * @param element The element to be added.
-   * @return The new chain with the added element.
-   * @throws NullPointerException if element is null.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public Chain<E> add(@Nullable E element) {
-    return new NonEmptyChain<E>(element, this);
-  }
-
-  /**
-   * Adds some new elements to the chain.
-   *
-   * @param elements The elements to be added.
-   * @return The new chain with the added elements.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public Chain<E> addAll(Iterable<E> elements) {
-    Chain<E> chain = this;
-    for (E element : elements) {
-      chain = chain.add(element);
-    }
-    return chain;
-  }
-
-  /**
-   * Gets an element from the chain.  A given index specifies the
-   * element, where zero refers to the first element in the chain and
-   * {@code size() - 1} refers to the last.
-   *
-   * @param index The index of the element to get.
-   * @return The specified element.
-   * @throws IllegalArgumentException if index is negative or too large.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public E get(@Nonnegative int index) {
-    Preconditions.checkArgument(index >= 0 && index < size());
-    Chain<E> chain = this;
-    for (int i = 0; i < size() - (index + 1); i += 1) {
-      chain = chain.getRest();
-    }
-    return chain.getLast();
-  }
-
-  /**
-   * Converts this chain to a set.
-   *
-   * @return The elements of this chain as a set.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public Set<E> toSet() {
-    return Sets.newHashSet(this);
-  }
-
-  /**
-   * Converts this chain to a list, preserving the chain's order.
-   *
-   * @return The elements of this chain as a list.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public List<E> toList() {
-    LinkedList<E> list = Lists.newLinkedList();
-    Chain<E> chain = this;
-    for (int i = 0; i < size(); i += 1) {
-      list.addFirst(chain.getLast());
-      chain = chain.getRest();
-    }
-    return list;
-  }
-
-  /**
-   * Given a chain that is an ancestor of this chain, returns the elements that
-   * have been added to the ancestor to make this chain.
-   *
-   * <p>For any ancestor chain {@code C} it is always true that
-   * {@code this.equals(C.addAll(this.toList(C)))}.
-   *
-   * @param ancestor The ancestor chain.
-   * @return A list of the elements elements added .
-   * @throws IllegalArgumentException if {@code chain} is not an ancestor.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public List<E> toList(Chain<E> ancestor) {
-    Preconditions.checkNotNull(ancestor);
-    LinkedList<E> list = Lists.newLinkedList();
-    Chain<E> chain = this;
-    while (chain != ancestor) {
-      if (chain.isEmpty()) {
-        throw new IllegalArgumentException("Not an ancestor chain: " + ancestor);
-      }
-      list.addFirst(chain.getLast());
-      chain = chain.getRest();
-    }
-    return list;
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof Chain<?>)) { return false; }
-    Chain<?> other = (Chain<?>) object;
-    if (size() != other.size()) { return false; }
-    Chain<E> c1 = this;
-    Chain<?> c2 = other;
-    for (int i = 0; i < size(); i += 1) {
-      if (!c1.getLast().equals(c2.getLast())) { return false; }
-      c1 = c1.getRest();
-      c2 = c2.getRest();
-    }
-    return true;
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hashCode(toList());
-  }
-
-  @Override
-  public String toString() {
-    return toList().toString();
-  }
-
-  /**
-   * Gets an iterator for this chain.  The iterator starts with the last element
-   * and moves towards the first.  If you want to iterate from first element to
-   * last, use {@link #toList()}.
-   */
-  @Override
-  public Iterator<E> iterator() {
-    return new LocalIterator<E>(this);
-  }
-
-  @NotThreadSafe
-  private static final class LocalIterator<F> implements Iterator<F> {
-    Chain<F> chain;
-
-    LocalIterator(Chain<F> chain) {
-      this.chain = chain;
-    }
-
-    @Override
-    public boolean hasNext() {
-      return !chain.isEmpty();
-    }
-
-    @Override
-    public F next() {
-      if (chain.isEmpty()) { throw new NoSuchElementException(); }
-      F value = chain.getLast();
-      chain = chain.getRest();
-      return value;
-    }
-
-    @Override
-    public void remove() {
-      throw new UnsupportedOperationException();
-    }
-  }
-
-  /**
-   * Converts an iterable of chains to an iterable of lists.  The resulting
-   * lists have the same ordering as the input chains.
-   *
-   * @param chains The chains to convert.
-   * @return The resulting lists.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static <T> Iterable<List<T>> toLists(Iterable<Chain<T>> chains) {
-    return Iterables.transform(chains, Chain.<T>toListFunction());
-  }
-
-  /**
-   * Gets a function that invokes the {@link #toList} method on its argument.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static <T> Function<Chain<T>, List<T>> toListFunction() {
-    return new Function<Chain<T>, List<T>>() {
-      @Override
-      public List<T> apply(Chain<T> chain) {
-        return chain.toList();
-      }
-    };
-  }
-
-  /**
-   * Converts an iterable of chains to an iterable of sets.
-   *
-   * @param chains The chains to convert.
-   * @return The resulting sets.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static <T> Iterable<Set<T>> toSets(Iterable<Chain<T>> chains) {
-    return Iterables.transform(chains, Chain.<T>toSetFunction());
-  }
-
-  /**
-   * Gets a function that invokes the {@link #toSet} method on its argument.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static <T> Function<Chain<T>, Set<T>> toSetFunction() {
-    return new Function<Chain<T>, Set<T>>() {
-      @Override
-      public Set<T> apply(Chain<T> chain) {
-        return chain.toSet();
-      }
-    };
-  }
-
-  /**
-   * Extends an iterable of chains with a given element.  For each member of the
-   * iterable, it creates a new member by adding the element to that member.
-   *
-   * @param chains The chains to be extended.
-   * @param element The element to extend them with.
-   * @return An iterable of the extended chains.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static <T> Iterable<Chain<T>> addToChains(Iterable<Chain<T>> chains, T element) {
-    return Iterables.transform(chains, addFunction(element));
-  }
-
-  /**
-   * Gets a function that adds a given element to a given chain.
-   *
-   * @param element The element to be added.
-   * @return A function that extends its argument with {@code element}.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static <T> Function<Chain<T>, Chain<T>> addFunction(@Nullable final T element) {
-    return new Function<Chain<T>, Chain<T>>() {
-      @Override
-      public Chain<T> apply(Chain<T> chain) {
-        return chain.add(element);
-      }
-    };
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/common/CookieStore.java b/src/com/google/enterprise/secmgr/common/CookieStore.java
deleted file mode 100644
index 7664c7c..0000000
--- a/src/com/google/enterprise/secmgr/common/CookieStore.java
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.secmgr.common;
-
-import java.util.Collection;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnegative;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-
-/**
- * A cookie store is an object that holds a collection of cookies.  The store
- * never holds two cookies with the same key.  When a cookie is added to a
- * store, if there's already a cookie in the store with that key, the new cookie
- * replaces the old one.
- * <p>
- * Because of this, the store may contain multiple cookies with the same name,
- * as long as the other parts of their keys differ.
- */
-@ParametersAreNonnullByDefault
-public interface CookieStore extends Collection<GCookie> {
-  /**
-   * Removes all cookies with expiration times earlier than a given time.
-   *
-   * @param timeStamp A time to use for expirations.
-   */
-  public void expireCookies(@Nonnegative long timeStamp);
-
-  /**
-   * Removes all cookies with expiration times earlier than the current time.
-   */
-  public void expireCookies();
-
-  /**
-   * Does this store contain a cookie with a given name?
-   *
-   * @param name The name to test for.
-   * @return True only if there's at least one cookie with that name in the
-   *     store.
-   */
-  @CheckReturnValue
-  public boolean contains(String name);
-
-  /**
-   * If this store contains a cookie with a given name, gets it.  If there are
-   * multiple cookies with that name, one of them is arbitrarily chosen.
-   *
-   * @param name The name to look for.
-   * @return A cookie with that name, or {@code null} if there are none.
-   */
-  @CheckReturnValue
-  @Nullable
-  public GCookie get(String name);
-
-  /**
-   * Does this store contain a cookie with a given key?
-   *
-   * @param key The key to test for.
-   * @return True only if there's a cookie with that key in the store.
-   */
-  @CheckReturnValue
-  public boolean contains(GCookie.Key key);
-
-  /**
-   * If this store contains a cookie with a given key, gets it.
-   *
-   * @param key The key to look for.
-   * @return The cookie with that key, or {@code null} if there isn't one.
-   */
-  @CheckReturnValue
-  @Nullable
-  public GCookie get(GCookie.Key key);
-}
diff --git a/src/com/google/enterprise/secmgr/common/CookieStoreImpl.java b/src/com/google/enterprise/secmgr/common/CookieStoreImpl.java
deleted file mode 100644
index fbd4d32..0000000
--- a/src/com/google/enterprise/secmgr/common/CookieStoreImpl.java
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.secmgr.common;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-
-import org.joda.time.DateTimeUtils;
-
-import java.util.AbstractCollection;
-import java.util.Iterator;
-import java.util.Map;
-
-import javax.annotation.Nonnegative;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.NotThreadSafe;
-
-/**
- * An implementation of a mutable cookie store that automatically expires
- * cookies whenever a cookie is added or the store is iterated.
- */
-@NotThreadSafe
-@ParametersAreNonnullByDefault
-final class CookieStoreImpl extends AbstractCollection<GCookie>
-    implements CookieStore {
-
-  @Nonnull private final Map<GCookie.Key, GCookie> map;
-
-  CookieStoreImpl() {
-    map = Maps.newHashMap();
-  }
-
-  @Override
-  public int size() {
-    return map.size();
-  }
-
-  // For a given cookie name, a store can contain exactly one partial key with
-  // that name, or no partial keys and any number of full keys.
-  @Override
-  public boolean add(GCookie cookie) {
-    GCookie.Key key = cookie.getKey();
-    GCookie oldCookie = map.get(key);
-    if (cookie.equals(oldCookie)) {
-      return false;
-    }
-    Iterables.removeIf(this, matchingKeyPredicate(key));
-    if (oldCookie != null) {
-      map.put(key, GCookie.builder(cookie).setCreationTime(oldCookie.getCreationTime()).build());
-    } else {
-      map.put(key, cookie);
-    }
-    return true;
-  }
-
-  private static Predicate<GCookie> matchingKeyPredicate(final GCookie.Key key) {
-    return key.isPartial()
-      ? new Predicate<GCookie>() {
-          @Override
-          public boolean apply(GCookie cookie) {
-            GCookie.Key other = cookie.getKey();
-            return key.getName().equals(other.getName());
-          }
-        }
-      : new Predicate<GCookie>() {
-          @Override
-          public boolean apply(GCookie cookie) {
-            GCookie.Key other = cookie.getKey();
-            return key.getName().equals(other.getName())
-                && (other.isPartial() || key.equals(other));
-          }
-        };
-  }
-
-  @Override
-  public Iterator<GCookie> iterator() {
-    return map.values().iterator();
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof Iterable<?>)) { return false; }
-    return ImmutableSet.copyOf(map.values()).equals(ImmutableSet.copyOf((Iterable<?>) object));
-  }
-
-  @Override
-  public int hashCode() {
-    return ImmutableSet.copyOf(map.values()).hashCode();
-  }
-
-  @Override
-  public void expireCookies(@Nonnegative long timeStamp) {
-    Iterables.removeIf(this, GCookie.isExpiredPredicate(timeStamp));
-  }
-
-  @Override
-  public void expireCookies() {
-    expireCookies(DateTimeUtils.currentTimeMillis());
-  }
-
-  @Override
-  public boolean contains(String name) {
-    return get(name) != null;
-  }
-
-  @Override
-  @Nullable
-  public GCookie get(String name) {
-    Preconditions.checkNotNull(name);
-    for (GCookie cookie : map.values()) {
-      if (name.equalsIgnoreCase(cookie.getName())) {
-        return cookie;
-      }
-    }
-    return null;
-  }
-
-  @Override
-  public boolean contains(GCookie.Key key) {
-    return get(key) != null;
-  }
-
-  @Override
-  @Nullable
-  public GCookie get(GCookie.Key key) {
-    Preconditions.checkNotNull(key);
-    return map.get(key);
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/common/FileUtil.java b/src/com/google/enterprise/secmgr/common/FileUtil.java
deleted file mode 100644
index 56ed934..0000000
--- a/src/com/google/enterprise/secmgr/common/FileUtil.java
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright 2008 Google Inc.
-//
-// 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.secmgr.common;
-
-import com.google.common.base.Preconditions;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * Utilities for finding files.
- */
-public class FileUtil {
-
-  private static String contextDirectory;
-  private static String commonDirectory;
-
-  private static final String GOOGLE3_TEST_UTIL_CLASS = "com.google.testing.util.TestUtil";
-  private static final String GET_SRC_DIR_METHOD = "getSrcDir";
-  private static final String GET_TMP_DIR_METHOD = "getTmpDir";
-  private static final String GOOGLE3_TESTDATA_ROOT =
-      "/google3/javatests/com/google/enterprise/secmgr/testdata";
-  private static final String NON_GOOGLE3_TESTDATA_ROOT = "testdata/mocktestdata/";
-
-  private static final String BEGIN_PEM_CERTIFICATE_MARKER = "-----BEGIN CERTIFICATE-----";
-  private static final String END_PEM_CERTIFICATE_MARKER = "-----END CERTIFICATE-----";
-
-  // don't instantiate
-  private FileUtil() {
-  }
-
-  /**
-   * Initialize the context and common directories for testing.  Chooses appropriate
-   * values for them depending on the testing context.
-   */
-  public static void initializeTestDirectories() {
-    Class<?> clazz;
-    try {
-      clazz = Class.forName(GOOGLE3_TEST_UTIL_CLASS);
-    } catch (ClassNotFoundException e) {
-      // no worries -- this just means we're not in a google3 environment
-      contextDirectory = NON_GOOGLE3_TESTDATA_ROOT;
-      commonDirectory = NON_GOOGLE3_TESTDATA_ROOT;
-      return;
-    }
-
-    Method m1;
-    Method m2;
-    try {
-      m1 = clazz.getDeclaredMethod(GET_SRC_DIR_METHOD);
-      m2 = clazz.getDeclaredMethod(GET_TMP_DIR_METHOD);
-    } catch (NoSuchMethodException e) {
-      throw new IllegalStateException(e);
-    }
-
-    String srcDir;
-    String tmpDir;
-    try {
-      srcDir = String.class.cast(m1.invoke(null));
-      tmpDir = String.class.cast(m2.invoke(null));
-    } catch (IllegalAccessException e) {
-      throw new IllegalStateException(e);
-    } catch (InvocationTargetException e) {
-      throw new IllegalStateException(e);
-    }
-
-    contextDirectory = srcDir + GOOGLE3_TESTDATA_ROOT;
-    commonDirectory = tmpDir;
-  }
-
-  /**
-   * Get the context directory.  This directory holds the config files used by
-   * the security manager.
-   *
-   * @return The context directory as a string.
-   */
-  public static String getContextDirectory() {
-    return contextDirectory;
-  }
-
-  /**
-   * Get the common directory.  This directory holds all persistent state maintained by
-   * the connector manager.
-   *
-   * @return The common directory as a string.
-   */
-  public static String getCommonDirectory() {
-    // Allow override via command-line flags so that large tests can easily
-    // specify a tmp directory.
-    String testTmpDir = System.getProperty("google3.tmpdir");
-    if (testTmpDir != null) {
-      return testTmpDir;
-    }
-    return commonDirectory;
-  }
-
-  /**
-   * Set the Context/Common directory.  To be called only from the servlet
-   * initialization in a production environment.
-   */
-  public static void setContextDirectory(String directory) {
-    contextDirectory = directory;
-    commonDirectory = directory;
-  }
-
-  /**
-   * Resolve relative filenames in the directory of the config files.
-   *
-   * @param filename A (potentially relative) filename.
-   * @return An absolute File object.
-   */
-  public static File getContextFile(String filename) {
-    Preconditions.checkNotNull(filename);
-    return getContextFile(new File(filename));
-  }
-
-  /**
-   * Resolve relative filenames in the directory of the config files.
-   *
-   * @param file A (potentially relative) File object.
-   * @return An absolute File object.
-   */
-  public static File getContextFile(File file) {
-    Preconditions.checkNotNull(file);
-    return (file.isAbsolute()) ? file : new File(getContextDirectory(), file.toString());
-  }
-
-  /**
-   * Resolve relative filenames in the common directory.
-   *
-   * @param filename A (potentially relative) filename.
-   * @return An absolute File object.
-   * @see #getCommonDirectory
-   */
-  public static File getCommonFile(String filename) {
-    Preconditions.checkNotNull(filename);
-    return getCommonFile(new File(filename));
-  }
-
-  /**
-   * Resolve relative filenames in the common directory.
-   *
-   * @param file A (potentially relative) File object.
-   * @return An absolute File object.
-   * @see #getCommonDirectory
-   */
-  public static File getCommonFile(File file) {
-    Preconditions.checkNotNull(file);
-    return (file.isAbsolute()) ? file : new File(getCommonDirectory(), file.toString());
-  }
-
-  /**
-   * Read a file's contents and return them as a string.
-   *
-   * @param file The file to read.
-   * @return The file's contents.
-   * @throws IOException if unable to read the file.
-   */
-  public static String readFile(File file)
-      throws IOException {
-    Preconditions.checkNotNull(file);
-    StringBuffer accumulator = new StringBuffer();
-    char[] buffer = new char[4096];
-    Reader reader = null;
-    try {
-      reader = new FileReader(file);
-      while (true) {
-        int nRead = reader.read(buffer);
-        if (nRead < 0) {
-          break;
-        }
-        accumulator.append(buffer, 0, nRead);
-      }
-    } finally {
-      if (reader != null) {
-        reader.close();
-      }
-    }
-    return accumulator.toString();
-  }
-
-  /**
-   * Read a PEM-encoded certificate file and return the Base64 part as a string.
-   *
-   * @param file The file to read.
-   * @return The certificate in Base64 encoding.
-   * @throws IOException if unable to read or parse the file.
-   */
-  public static String readPEMCertificateFile(File file)
-      throws IOException {
-    String certFile = readFile(file);
-    int start = certFile.indexOf(BEGIN_PEM_CERTIFICATE_MARKER);
-    if (start < 0) {
-      throw new IOException("Certificate file missing begin marker");
-    }
-    start += BEGIN_PEM_CERTIFICATE_MARKER.length();
-    int end = certFile.indexOf(END_PEM_CERTIFICATE_MARKER, start);
-    if (end < 0) {
-      throw new IOException("Certificate file missing end marker");
-    }
-    return certFile.substring(start, end - 1);
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/common/GCookie.java b/src/com/google/enterprise/secmgr/common/GCookie.java
deleted file mode 100644
index cd638ae..0000000
--- a/src/com/google/enterprise/secmgr/common/GCookie.java
+++ /dev/null
@@ -1,1873 +0,0 @@
-// Copyright 2011 Google Inc.
-//
-// 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.secmgr.common;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.CharMatcher;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Splitter;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-
-import org.joda.time.DateTimeUtils;
-
-import java.net.URI;
-import java.util.Calendar;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
-import java.util.logging.Logger;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnegative;
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-import javax.annotation.concurrent.NotThreadSafe;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * An immutable cookie implementation that complies with RFC 6265.  Note that
- * this implementation does not (yet) support IDNA (RFC 5890) even though that
- * is required by the specification.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public final class GCookie {
-  private static final Logger LOGGER = Logger.getLogger(GCookie.class.getName());
-
-  // A cookie with its name in this list will always have its value logged in
-  // cleartext.
-  private static final ImmutableList<String> ALWAYS_SHOW_VALUE =
-      ImmutableList.of("GSA_SESSION_ID", "JSESSIONID");
-  private static final char OBFUSCATED_VALUE_PREFIX = '#';
-  private static final char VALUE_SEPARATOR = '=';
-  private static final char REQUEST_SEPARATOR = ';';
-  private static final String REQUEST_SEPARATOR_STRING = "; ";
-  private static final char ATTR_SEPARATOR = ';';
-  private static final String ATTR_SEPARATOR_STRING = "; ";
-  private static final char PATH_SEPARATOR = '/';
-  public static final String UNIVERSAL_PATH = "/";
-
-  private static final CharMatcher WSP = CharMatcher.anyOf(" \t");
-
-  /**
-   * Characters allowed in a cookie name.  Servers are supposed to restrict
-   * names to the HTTP token syntax.
-   */
-  private static final CharMatcher COOKIE_NAME = CharMatcher.noneOf(";=");
-
-  /**
-   * Characters allowed in a cookie value.  Servers are supposed to restrict
-   * values to octets between 0x21 and 0x7E inclusive, except for {@code '"'},
-   * {@code '\\'}, {@code ','}, and {@code ';'}.  The value may optionally be
-   * surrounded by double quotes.
-   */
-  private static final CharMatcher COOKIE_VALUE = CharMatcher.noneOf(";");
-
-  /**
-   * Cookies are distinguished by their name, their domain, and their path.  If
-   * two cookies have the same values for those elements, they are considered to
-   * be the same cookie.  This class formalizes that concept by providing an
-   * object representing the distinguishing components.
-   */
-  @Immutable
-  @ParametersAreNonnullByDefault
-  public static final class Key {
-    @Nonnull private final String name;
-    @Nonnull private final String domain;
-    @Nonnull private final String path;
-
-    private Key(String name, String domain, String path) {
-      this.name = name;
-      this.domain = domain;
-      this.path = path;
-    }
-
-    @Override
-    public boolean equals(Object object) {
-      if (object == this) { return true; }
-      if (!(object instanceof Key)) { return false; }
-      Key other = (Key) object;
-      return getName().equalsIgnoreCase(other.getName())
-          && getDomain().equalsIgnoreCase(other.getDomain())
-          && getPath().equals(other.getPath());
-    }
-
-    @Override
-    public int hashCode() {
-      return Objects.hashCode(name.toLowerCase(Locale.US), domain.toLowerCase(Locale.US), path);
-    }
-
-    // True only of cookies that didn't come from a set-cookie header.
-    boolean isPartial() {
-      return domain.isEmpty() && path.isEmpty();
-    }
-
-    /**
-     * Gets the name for this key.
-     *
-     * @return This key's name.
-     */
-    @CheckReturnValue
-    @Nonnull
-    public String getName() {
-      return name;
-    }
-
-    /**
-     * Gets the domain for this key.
-     *
-     * @return This key's domain.
-     */
-    @CheckReturnValue
-    @Nonnull
-    public String getDomain() {
-      return domain;
-    }
-
-    /**
-     * Gets the path for this key.
-     *
-     * @return This key's path.
-     */
-    @CheckReturnValue
-    @Nonnull
-    public String getPath() {
-      return path;
-    }
-  }
-
-  @Nonnull private final Key key;
-  @Nonnull private final String value;
-  @Nonnegative private final long expires;
-  @Nonnegative private final long creationTime;
-  @Nonnegative private final long lastAccessTime;
-  private final boolean persistent;
-  private final boolean hostOnly;
-  private final boolean secureOnly;
-  private final boolean httpOnly;
-
-  private GCookie(Key key, String value, @Nonnegative long expires, @Nonnegative long creationTime,
-      @Nonnegative long lastAccessTime, boolean persistent, boolean hostOnly, boolean secureOnly,
-      boolean httpOnly) {
-    this.key = key;
-    this.value = value;
-    this.expires = expires;
-    this.creationTime = creationTime;
-    this.lastAccessTime = lastAccessTime;
-    this.persistent = persistent;
-    this.hostOnly = hostOnly;
-    this.secureOnly = secureOnly;
-    this.httpOnly = httpOnly;
-  }
-
-  // **************** Accessors ****************
-
-  /**
-   * Gets the cookie's key, an object that embodies what it means for two
-   * cookies to have the "same name".
-   *
-   * @return The key.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public Key getKey() {
-    return key;
-  }
-
-  /**
-   * Gets the cookie's name, which is a non-empty case-insensitve string.
-   *
-   * @return The name.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public String getName() {
-    return key.getName();
-  }
-
-  /**
-   * Gets the cookie's value.
-   *
-   * @return The value.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public String getValue() {
-    return value;
-  }
-
-  /**
-   * Gets the cookie's expiration time in milliseconds from the epoch.
-   *
-   * @return The expiration time.
-   */
-  @CheckReturnValue
-  @Nonnegative
-  public long getExpires() {
-    return expires;
-  }
-
-  /**
-   * Gets the cookie's domain.
-   *
-   * @return The domain.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public String getDomain() {
-    return key.getDomain();
-  }
-
-  /**
-   * Gets the cookie's path.
-   *
-   * @return The path.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public String getPath() {
-    return key.getPath();
-  }
-
-  /**
-   * Gets the cookie's creation time in milliseconds from the epoch.
-   *
-   * @return The creation time.
-   */
-  @CheckReturnValue
-  @Nonnegative
-  public long getCreationTime() {
-    return creationTime;
-  }
-
-  /**
-   * Gets the cookie's last-access time in milliseconds from the epoch.
-   *
-   * @return The last-access time.
-   */
-  @CheckReturnValue
-  @Nonnegative
-  public long getLastAccessTime() {
-    return lastAccessTime;
-  }
-
-  /**
-   * Is the cookie persistent?
-   *
-   * @return True if the cookie is persistent.
-   */
-  @CheckReturnValue
-  public boolean getPersistent() {
-    return persistent;
-  }
-
-  /**
-   * Should this cookie be restricted to the host that exactly matches its domain?
-   *
-   * @return True if the cookie should be restricted.
-   */
-  @CheckReturnValue
-  public boolean getHostOnly() {
-    return hostOnly;
-  }
-
-  /**
-   * Is the cookie valid only for "secure" connections?
-   *
-   * @return True if the cookie is usable only for HTTPS and other secure
-   *     connections.
-   */
-  @CheckReturnValue
-  public boolean getSecureOnly() {
-    return secureOnly;
-  }
-
-  /**
-   * Should the cookie be restricted to HTTP messages?  If true, Javascript
-   * client programs can't access this cookie.
-   *
-   * @return True if the cookie should be restricted.
-   */
-  @CheckReturnValue
-  public boolean getHttpOnly() {
-    return httpOnly;
-  }
-
-  /**
-   * Is this cookie expired?
-   *
-   * @param timeStamp The reference time at which to determine the answer.
-   * @return True if the cookie is expired.
-   */
-  @CheckReturnValue
-  public boolean isExpired(@Nonnegative long timeStamp) {
-    Preconditions.checkArgument(timeStamp >= 0);
-    return getExpires() <= timeStamp;
-  }
-
-  /**
-   * Gets a predicate that computes {@link #isExpired}.
-   *
-   * @param timeStamp The reference time at which to determine the answer.
-   * @return A predicate that's true if a given cookie is expired at the
-   *     reference time.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Predicate<GCookie> isExpiredPredicate(@Nonnegative final long timeStamp) {
-    Preconditions.checkArgument(timeStamp >= 0);
-    return new Predicate<GCookie>() {
-      @Override
-      public boolean apply(GCookie cookie) {
-        return cookie.getExpires() <= timeStamp;
-      }
-    };
-  }
-
-  /**
-   * Gets the "maximum age" of this cookie.  Normally this isn't used; it's provided
-   * for compatibility.  Instead use {@link #getExpires}.
-   *
-   * @return The "maximum age" of this cookie in seconds, or {@code -1} for a
-   *     session cookie.
-   */
-  @CheckReturnValue
-  public int getMaxAge() {
-    if (!getPersistent()) {
-      return -1;
-    }
-    if (getExpires() < getCreationTime()) {
-      return 0;
-    }
-    long deltaSeconds = ((getExpires() - getCreationTime()) + 500) / 1000;
-    return (deltaSeconds > Integer.MAX_VALUE)
-        ? -1
-        : (int) deltaSeconds;
-  }
-
-  // **************** Equality ****************
-
-  /** Note that equality doesn't consider any of the cookie's times. */
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof GCookie)) { return false; }
-    GCookie other = (GCookie) object;
-    return getKey().equals(other.getKey())
-        && getValue().equals(other.getValue())
-        && getPersistent() == other.getPersistent()
-        && getSecureOnly() == other.getSecureOnly()
-        && getHttpOnly() == other.getHttpOnly();
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hashCode(getKey(), getValue(), getPersistent(), getSecureOnly(), getHttpOnly());
-  }
-
-  /**
-   * Checks whether a given cookie has the same name as this cookie.
-   *
-   * @param cookie The cookie to compare against.
-   * @return True only if the names match.
-   */
-  @CheckReturnValue
-  public boolean hasSameName(GCookie cookie) {
-    return getName().equalsIgnoreCase(cookie.getName());
-  }
-
-  /**
-   * Checks whether any of some given cookies have the same name as this cookie.
-   *
-   * @param cookies The cookies to compare against.
-   * @return True only if the name of one of the cookies matches.
-   */
-  @CheckReturnValue
-  public boolean hasSameName(Iterable<GCookie> cookies) {
-    for (GCookie cookie : cookies) {
-      if (hasSameName(cookie)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Checks whether a given cookie has the same key as this cookie.
-   *
-   * @param cookie The cookie to compare against.
-   * @return True only if the keys match.
-   */
-  @CheckReturnValue
-  public boolean hasSameKey(GCookie cookie) {
-    return getKey().equals(cookie.getKey());
-  }
-
-  /**
-   * Checks whether any of some given cookies have the same key as this cookie.
-   *
-   * @param cookies The cookies to compare against.
-   * @return True only if the key of one of the cookies matches.
-   */
-  @CheckReturnValue
-  public boolean hasSameKey(Iterable<GCookie> cookies) {
-    for (GCookie cookie : cookies) {
-      if (hasSameKey(cookie)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  // **************** Logging support ****************
-
-  @Override
-  public String toString() {
-    return responseHeaderString(false);
-  }
-
-  /**
-   * Generates a log message containing a description of some given cookies in
-   * request format.
-   *
-   * @param prefix A prefix for the log message.
-   * @param cookies The cookies to be described.
-   * @return A suitably formatted log message.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static String requestCookiesMessage(String prefix, Iterable<GCookie> cookies) {
-    StringBuilder builder = new StringBuilder();
-    builder.append(prefix);
-    builder.append(": ");
-    if (Iterables.isEmpty(cookies)) {
-      builder.append("(none)");
-    } else {
-      writeRequest(cookies, false, builder);
-    }
-    return builder.toString();
-  }
-
-  /**
-   * Generates a log message containing a description of some given cookies in
-   * response format.
-   *
-   * @param prefix A prefix for the log message.
-   * @param cookies The cookies to be described.
-   * @return A suitably formatted log message.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static String responseCookiesMessage(String prefix, Iterable<GCookie> cookies) {
-    StringBuilder builder = new StringBuilder();
-    builder.append(prefix);
-    builder.append(": ");
-    if (Iterables.isEmpty(cookies)) {
-      builder.append("(none)");
-    } else {
-      boolean needSeparator = false;
-      for (GCookie cookie : cookies) {
-        if (needSeparator) {
-          builder.append(", ");
-        } else {
-          needSeparator = true;
-        }
-        cookie.writeResponse(false, builder);
-      }
-    }
-    return builder.toString();
-  }
-
-  // **************** URI filtering ****************
-
-  /**
-   * Checks if this cookie is suitable for a given target URI.
-   *
-   * @param uri The URI object to test against.
-   * @return True if the cookie is suitable to be sent to the URI.
-   */
-  @CheckReturnValue
-  public boolean isGoodFor(URI uri) {
-    return domainMatch(getDomain(), getHostOnly(), computeRequestHost(uri))
-        && pathMatch(getPath(), uri.getPath())
-        && secureOnlyMatch(getSecureOnly(), uri.getScheme());
-  }
-
-  private static boolean domainMatch(String cookieDomain, boolean hostOnly, String requestHost) {
-    if (cookieDomain.isEmpty()) {
-      return true;
-    }
-    requestHost = requestHost.toLowerCase(Locale.US);
-    if (requestHost.equals(cookieDomain)) {
-      return true;
-    }
-    if (hostOnly) {
-      return false;
-    }
-    return requestHost.endsWith(cookieDomain)
-        && requestHost.charAt(requestHost.length() - cookieDomain.length() - 1) == '.';
-  }
-
-  private static boolean pathMatch(String cookiePath, String requestPath) {
-    return cookiePath.isEmpty()
-        || requestPath.equals(cookiePath)
-        || (requestPath.startsWith(cookiePath)
-            && (lastChar(cookiePath) == PATH_SEPARATOR
-                || requestPath.charAt(cookiePath.length()) == PATH_SEPARATOR));
-  }
-
-  private static char firstChar(String string) {
-    return string.charAt(0);
-  }
-
-  private static char lastChar(String string) {
-    return string.charAt(string.length() - 1);
-  }
-
-  private static boolean secureOnlyMatch(boolean secureOnly, String requestProtocol) {
-    return !secureOnly || "https".equalsIgnoreCase(requestProtocol);
-  }
-
-  /**
-   * Determine whether there are any cookies to send.
-   *
-   * @param uri The URI of the authority.
-   * @param userAgentCookies The cookies received from the user agent.
-   * @param authorityCookies The cookies previously received from the authority.
-   * @return True if there are some cookies to be sent.
-   */
-  @CheckReturnValue
-  public static boolean haveCookiesToSend(URI uri, Iterable<GCookie> userAgentCookies,
-      Iterable<GCookie> authorityCookies) {
-    return anyCookieGoodFor(userAgentCookies, uri)
-        || anyCookieGoodFor(authorityCookies, uri);
-  }
-
-  private static boolean anyCookieGoodFor(Iterable<GCookie> cookies, URI uri) {
-    for (GCookie cookie : cookies) {
-      if (cookie.isGoodFor(uri)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Compute the cookies to send to a given authority.  Authority cookies have
-   * priority over user-agent cookies.
-   *
-   * @param uri The URI of the authority.
-   * @param userAgentCookies The cookies received from the user agent.
-   * @param authorityCookies The cookies previously received from the authority.
-   * @param store The cookie store to add the "to-send" cookies to.
-   */
-  public static void computeCookiesToSend(URI uri, Iterable<GCookie> userAgentCookies,
-      Iterable<GCookie> authorityCookies, CookieStore store) {
-    for (GCookie cookie : authorityCookies) {
-      if (cookie.isGoodFor(uri)) {
-        store.add(cookie);
-      }
-    }
-    for (GCookie cookie : userAgentCookies) {
-      if (cookie.isGoodFor(uri) && !store.contains(cookie.getName())) {
-        store.add(cookie);
-      }
-    }
-  }
-
-  /**
-   * Compute the cookies to send to a given authority.  Authority cookies have
-   * priority over user-agent cookies.
-   *
-   * @param uri The URI of the authority.
-   * @param userAgentCookies The cookies received from the user agent.
-   * @param authorityCookies The cookies previously received from the authority.
-   * @return A cookie store containing the "to-send" cookies.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static CookieStore computeCookiesToSend(URI uri,
-      Iterable<GCookie> userAgentCookies, Iterable<GCookie> authorityCookies) {
-    CookieStore store = makeStore();
-    computeCookiesToSend(uri, userAgentCookies, authorityCookies, store);
-    store.expireCookies();
-    return store;
-  }
-
-  // **************** Cookie store ****************
-
-  /**
-   * Makes a new empty store.
-   *
-   * @return A new empty store.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static CookieStore makeStore() {
-    return new CookieStoreImpl();
-  }
-
-  /**
-   * Makes a new store and adds some cookies to it.
-   *
-   * @param cookies The cookies to be added.
-   * @return A new store containing the given cookies.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static CookieStore makeStore(Iterable<GCookie> cookies) {
-    CookieStore store = makeStore();
-    Iterables.addAll(store, cookies);
-    store.expireCookies();
-    return store;
-  }
-
-  /**
-   * Merge two collections of cookies together.
-   *
-   * @param cookies1 The first collection.
-   * @param cookies2 The second collection, which overrides the first.
-   * @return The merged collection.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Iterable<GCookie> mergeCookies(Iterable<GCookie> cookies1,
-      Iterable<GCookie> cookies2) {
-    CookieStore store = makeStore();
-    Iterables.addAll(store, cookies1);
-    Iterables.addAll(store, cookies2);
-    store.expireCookies();
-    return store;
-  }
-
-  // **************** Conversions to/from Java cookies ****************
-
-  /**
-   * Converts a cookie to a {@link GCookie}.
-   *
-   * @param cookie A cookie to be converted.
-   * @return The converted cookie.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static GCookie fromCookie(Cookie cookie) {
-    return builder(cookie).build();
-  }
-
-  /**
-   * Converts this {@link GCookie} to a {@link Cookie}.
-   *
-   * @return A newly created {@link Cookie}.
-   * @throws RuntimeException if unable to perform the conversion.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public Cookie toCookie() {
-    Cookie cookie = new Cookie(getName(), getValue());
-    cookie.setValue(getValue());
-    if (getDomain() != null) {
-      cookie.setDomain(getDomain());
-    }
-    cookie.setPath(getPath());
-    cookie.setSecure(getSecureOnly());
-    cookie.setMaxAge(getMaxAge());
-    return cookie;
-  }
-
-  /**
-   * Converts some {@link GCookie}s to {@link Cookie}s.
-   *
-   * @param cookies The cookies to be converted.
-   * @return The converted cookies, except for those that fail to convert.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static ImmutableList<Cookie> toCookie(Iterable<GCookie> cookies) {
-    ImmutableList.Builder<Cookie> builder = ImmutableList.builder();
-    for (GCookie cookie : cookies) {
-      Cookie c;
-      try {
-        c = cookie.toCookie();
-      } catch (RuntimeException e) {
-        continue;
-      }
-      builder.add(c);
-    }
-    return builder.build();
-  }
-
-  // **************** Generating HTTP headers ****************
-
-  /**
-   * Gets a string representing the given cookies in request format.
-   *
-   * @param cookies The cookies to convert.
-   * @param showValues If false, the cookie's value will be obfuscated in the
-   *     returned string.
-   * @return The formatted string.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static String requestHeaderString(Iterable<GCookie> cookies,
-      boolean showValues) {
-    StringBuilder builder = new StringBuilder();
-    writeRequest(cookies, showValues, builder);
-    return builder.toString();
-  }
-
-  /**
-   * Writes a representation of the given cookies in request format.
-   *
-   * @param cookies The cookies to write.
-   * @param showValues If false, the cookie's value will be obfuscated in the
-   *     returned string.
-   * @param builder A string builder to write the representation to.
-   */
-  public static void writeRequest(Iterable<GCookie> cookies, boolean showValues,
-      StringBuilder builder) {
-    boolean needSeparator = false;
-    for (GCookie cookie : cookies) {
-      if (needSeparator) {
-        builder.append(REQUEST_SEPARATOR_STRING);
-      } else {
-        needSeparator = true;
-      }
-      cookie.writeRequest(showValues, builder);
-    }
-  }
-
-  /**
-   * Gets a string representing this cookie in request format.
-   *
-   * @param showValues If false, the cookie's value will be obfuscated in the
-   *     returned string.
-   * @return The formatted string.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public String requestHeaderString(boolean showValues) {
-    StringBuilder builder = new StringBuilder();
-    writeRequest(showValues, builder);
-    return builder.toString();
-  }
-
-  /**
-   * Writes a representation of this cookie in request format.
-   *
-   * @param showValues If false, the cookie's value will be obfuscated in the
-   *     returned string.
-   * @param builder A string builder to write the representation to.
-   */
-  public void writeRequest(boolean showValues, StringBuilder builder) {
-    writeBinding(showValues, builder);
-  }
-
-  /**
-   * Gets a string representing this cookie in response format.
-   *
-   * @param showValues If false, the cookie's value will be obfuscated in the
-   *     returned string.
-   * @return The formatted string.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public String responseHeaderString(boolean showValues) {
-    StringBuilder builder = new StringBuilder();
-    writeResponse(showValues, builder);
-    return builder.toString();
-  }
-
-  /**
-   * Writes a representation of this cookie in response format.
-   *
-   * @param showValues If false, the cookie's value will be obfuscated in the
-   *     returned string.
-   * @param builder A string builder to write the representation to.
-   */
-  public void writeResponse(boolean showValues, StringBuilder builder) {
-    writeBinding(showValues, builder);
-    if (getExpires() < Long.MAX_VALUE) {
-      writeAttr(AttrName.EXPIRES, HttpUtil.generateHttpDate(getExpires()), builder);
-    }
-    writeAttr(AttrName.MAX_AGE, getMaxAge(), builder);
-    if (!(getHostOnly() || getDomain().isEmpty())) {
-      String domain = getDomain();
-      if (!domain.startsWith(".")) {
-        domain = "." + domain;
-      }
-      writeAttr(AttrName.DOMAIN, domain, builder);
-    }
-    writeAttr(AttrName.PATH, getPath(), builder);
-    writeAttr(AttrName.SECURE, getSecureOnly(), builder);
-    writeAttr(AttrName.HTTP_ONLY, getHttpOnly(), builder);
-  }
-
-  private void writeBinding(boolean showValues, StringBuilder builder) {
-    builder.append(getName());
-    builder.append(VALUE_SEPARATOR);
-    if (!getValue().isEmpty()) {
-      if (showValues || alwaysShowValue(getName())) {
-        builder.append(getValue());
-      } else {
-        builder.append(OBFUSCATED_VALUE_PREFIX);
-        builder.append(
-            Base64.encodeWebSafe(SecurePasswordHasher.macInput(getName(), getValue()), false));
-      }
-    }
-  }
-
-  private static void writeAttr(AttrName param, String value, StringBuilder builder) {
-    if (!value.isEmpty()) {
-      builder.append(ATTR_SEPARATOR_STRING);
-      builder.append(param.toString());
-      builder.append(VALUE_SEPARATOR);
-      builder.append(value);
-    }
-  }
-
-  private static void writeAttr(AttrName param, int value, StringBuilder builder) {
-    if (value >= 0) {
-      writeAttr(param, Integer.toString(value), builder);
-    }
-  }
-
-  private static void writeAttr(AttrName param, boolean value, StringBuilder builder) {
-    if (value) {
-      builder.append(ATTR_SEPARATOR_STRING);
-      builder.append(param.toString());
-    }
-  }
-
-  private static boolean alwaysShowValue(String name) {
-    for (String name2 : ALWAYS_SHOW_VALUE) {
-      if (name2.equalsIgnoreCase(name)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  private enum AttrName {
-    EXPIRES("Expires"),
-    MAX_AGE("Max-Age"),
-    DOMAIN("Domain"),
-    PATH("Path"),
-    SECURE("Secure"),
-    HTTP_ONLY("HttpOnly");
-
-    @Nonnull private final String name;
-
-    private AttrName(String name) {
-      this.name = name;
-    }
-
-    @Override
-    public String toString() {
-      return name;
-    }
-  }
-
-  // **************** Parsers ****************
-
-  /**
-   * Parses request header values to produce cookies.  Returns Java cookies for
-   * use by legacy code.
-   *
-   * @param headers The header values to parse.
-   * @return An immutable list of the parsed cookies.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static ImmutableList<Cookie> legacyParseRequestHeaders(Iterable<String> headers) {
-    CookieStore store = makeStore();
-    parseRequestHeaders(headers, null, null, store);
-    return toCookie(store);
-  }
-
-  /**
-   * Parses request header values to produce cookies.
-   *
-   * @param headers The header values to parse.
-   * @param requestUri The request URI.
-   * @param sessionId A session ID to add to log messages.
-   * @param store A cookie store to which the parsed cookies will be added.
-   */
-  public static void parseRequestHeaders(Iterable<String> headers, URI requestUri, String sessionId,
-      CookieStore store) {
-    long now = DateTimeUtils.currentTimeMillis();
-    for (String header : headers) {
-      for (String cookiePair : REQUEST_SPLITTER.split(header)) {
-        Builder builder;
-        try {
-          builder = parseCookiePair(cookiePair, now);
-        } catch (ParseException e) {
-          LOGGER.info(SecurityManagerUtil.sessionLogMessage(sessionId, e.getMessage()));
-          continue;
-        }
-        store.add(builder.build());
-      }
-    }
-    store.expireCookies(now);
-  }
-
-  /**
-   * Parses response header values to produce cookies.
-   *
-   * @param headers The header values to parse.
-   * @param requestUri The request URI corresponding to this response.
-   * @param sessionId A session ID to add to log messages.
-   * @param store A cookie store to which the parsed cookies will be added.
-   */
-  public static void parseResponseHeaders(Iterable<String> headers, URI requestUri,
-      String sessionId, CookieStore store) {
-    long now = DateTimeUtils.currentTimeMillis();
-    for (String header : headers) {
-      GCookie cookie;
-      try {
-        cookie = parseResponseHeader(header, requestUri, now);
-      } catch (ParseException e) {
-        LOGGER.info(SecurityManagerUtil.sessionLogMessage(sessionId, e.getMessage()));
-        continue;
-      }
-      store.add(cookie);
-    }
-    store.expireCookies(now);
-  }
-
-  private static GCookie parseResponseHeader(String header, URI requestUri, long now)
-      throws ParseException {
-    List<String> parts = ImmutableList.copyOf(ATTR_SPLITTER.split(header));
-    if (parts.isEmpty()) {
-      parseError("No value separator in: %s", Stringify.object(header));
-    }
-    Builder builder = parseCookiePair(parts.get(0), now)
-        .setCreationTime(now)
-        .setLastAccessTime(now);
-    Map<AttrName, Object> parsedAttrs = parseAttrs(parts.subList(1, parts.size()));
-
-    Long maxAgeRaw = Long.class.cast(parsedAttrs.get(AttrName.MAX_AGE));
-    if (maxAgeRaw != null) {
-      long maxAge = maxAgeRaw.longValue();
-      long expires;
-      if (maxAge <= 0) {
-        expires = 0;
-      } else {
-        expires = now + maxAge;
-        if (expires < 0) {
-          // Means we got an overflow.
-          expires = Long.MAX_VALUE;
-        }
-      }
-      builder.setPersistent(true);
-      builder.setExpires(expires);
-    } else {
-      Long expiresRaw = Long.class.cast(parsedAttrs.get(AttrName.EXPIRES));
-      if (expiresRaw != null) {
-        long expires = expiresRaw.longValue();
-        if (expires >= 0) {
-          builder.setPersistent(true);
-          builder.setExpires(expires);
-        } else {
-          builder.setPersistent(false);
-          builder.setExpires(Long.MAX_VALUE);
-        }
-      }
-    }
-
-    if (requestUri != null) {
-      String requestHost = computeRequestHost(requestUri);
-      String domain = String.class.cast(parsedAttrs.get(AttrName.DOMAIN));
-      if (domain == null) {
-        domain = "";
-      }
-      if (isPublicSuffix(domain)) {
-        if (!domain.equals(requestHost)) {
-          parseError("Cookie domain %s is a public domain",
-              Stringify.object(domain));
-        }
-        domain = "";
-      }
-      if (domain.isEmpty()) {
-        builder.setHostOnly(true);
-        builder.setDomain(requestHost);
-      } else {
-        if (!domainMatch(domain, false, requestHost)) {
-          parseError("Cookie domain %s doesn't match request host %s",
-              Stringify.object(domain), Stringify.object(requestHost));
-        }
-        builder.setHostOnly(false);
-        builder.setDomain(domain);
-      }
-
-      String path = String.class.cast(parsedAttrs.get(AttrName.PATH));
-      if (path == null || path.isEmpty()) {
-        builder.setPath(computeDefaultPath(requestUri));
-      } else {
-        builder.setPath(path);
-      }
-    }
-
-    builder.setSecureOnly(parsedAttrs.get(AttrName.SECURE) != null);
-    builder.setHttpOnly(parsedAttrs.get(AttrName.HTTP_ONLY) != null);
-
-    return builder.build();
-  }
-
-  private static Builder parseCookiePair(String cookiePair, long now)
-      throws ParseException {
-    int vsep = cookiePair.indexOf(VALUE_SEPARATOR);
-    if (vsep < 0) {
-      parseError("No value separator in: %s",
-          Stringify.object(cookiePair));
-    }
-    String name = WSP.trimFrom(cookiePair.substring(0, vsep));
-    if (!isCookieName(name)) {
-      parseError("Invalid cookie name %s in: %s",
-          Stringify.object(name), Stringify.object(cookiePair));
-    }
-    String value = WSP.trimFrom(cookiePair.substring(vsep + 1));
-    if (!isCookieValue(value)) {
-      parseError("Invalid cookie value %s in: %s",
-          Stringify.object(value), Stringify.object(cookiePair));
-    }
-    return builder(name, now).setValue(value);
-  }
-
-  private static final Splitter REQUEST_SPLITTER =
-      Splitter.on(REQUEST_SEPARATOR).trimResults().omitEmptyStrings();
-
-  private static final Splitter ATTR_SPLITTER =
-      Splitter.on(ATTR_SEPARATOR).trimResults().omitEmptyStrings();
-
-  private static Map<AttrName, Object> parseAttrs(List<String> unparsedAttrs) {
-    Map<AttrName, Object> parsedAttrs = Maps.newHashMap();
-    for (String unparsed : unparsedAttrs) {
-      String aname;
-      String avalue;
-      int vsep = unparsed.indexOf(VALUE_SEPARATOR);
-      if (vsep < 0) {
-        aname = WSP.trimFrom(unparsed);
-        avalue = "";
-      } else {
-        aname = WSP.trimFrom(unparsed.substring(0, vsep));
-        avalue = WSP.trimFrom(unparsed.substring(vsep + 1));
-      }
-      AttrName attrName = findAttrName(aname);
-      if (attrName != null) {
-        Object value = dispatchAttr(attrName, avalue);
-        if (value != null) {
-          parsedAttrs.put(attrName, value);
-        }
-      }
-    }
-    return parsedAttrs;
-  }
-
-  private static AttrName findAttrName(String aname) {
-    for (AttrName attrName : EnumSet.allOf(AttrName.class)) {
-      if (attrName.toString().equalsIgnoreCase(aname)) {
-        return attrName;
-      }
-    }
-    return null;
-  }
-
-  private static Object dispatchAttr(AttrName attrName, String avalue) {
-    switch (attrName) {
-      case EXPIRES: return parseExpires(avalue);
-      case MAX_AGE: return parseMaxAge(avalue);
-      case DOMAIN: return parseDomain(avalue);
-      case PATH: return parsePath(avalue);
-      case SECURE: return parseSecure(avalue);
-      case HTTP_ONLY: return parseHttpOnly(avalue);
-      default: throw new IllegalStateException("Unknown AttrName: " + attrName);
-    }
-  }
-
-  private static Long parseExpires(String expires) {
-    try {
-      return parseDate(expires);
-    } catch (IllegalArgumentException e) {
-      LOGGER.info("Error parsing Expires attribute: " + e.getMessage());
-      return null;
-    }
-  }
-
-  private static Long parseMaxAge(String maxAge) {
-    try {
-      return Long.parseLong(maxAge);
-    } catch (NumberFormatException e) {
-      return null;
-    }
-  }
-
-  private static String parseDomain(String domain) {
-    return domain.isEmpty() ? null : canonicalizeDomain(domain);
-  }
-
-  private static String canonicalizeDomain(String domain) {
-    if (domain.startsWith(".")) {
-      domain = domain.substring(1);
-    }
-    try {
-      // Do full canonicalization if possible.
-      return HttpUtil.canonicalizeDomainName(domain);
-    } catch (IllegalArgumentException e) {
-      // Otherwise fall back to simple case folding.
-      return domain.toLowerCase(Locale.US);
-    }
-  }
-
-  private static boolean isPublicSuffix(String domain) {
-    // TODO(cph): should check for "public suffix" here.  See
-    // <http://publicsuffix.org/>.
-    return false;
-  }
-
-  private static String parsePath(String path) {
-    return (path.isEmpty() || firstChar(path) != PATH_SEPARATOR)
-        ? ""
-        : path;
-  }
-
-  private static boolean parseSecure(String avalue) {
-    return true;
-  }
-
-  private static boolean parseHttpOnly(String avalue) {
-    return true;
-  }
-
-  private static String computeRequestHost(URI requestUri) {
-    String host = requestUri.getHost();
-    try {
-      return HttpUtil.canonicalizeDomainName(host);
-    } catch (IllegalArgumentException e) {
-      return host.toLowerCase(Locale.US);
-    }
-  }
-
-  private static String computeDefaultPath(URI requestUri) {
-    String path = requestUri.getPath();
-    if (path.isEmpty() || firstChar(path) != PATH_SEPARATOR) {
-      return UNIVERSAL_PATH;
-    }
-    int lastSeparator = path.lastIndexOf(PATH_SEPARATOR);
-    return (lastSeparator > 0)
-        ? path.substring(0, lastSeparator)
-        : UNIVERSAL_PATH;
-  }
-
-  private static String parseError(String format, Object... args)
-      throws ParseException {
-    throw new ParseException(String.format(format, args));
-  }
-
-  /**
-   * An exception that's thrown by a cookie parser when the input can't be
-   * parsed.
-   */
-  public static final class ParseException extends Exception {
-    ParseException(String message) { super(message); }
-  }
-
-  // **************** Element predicates and canonicalizers ****************
-
-  /**
-   * Is the given string a valid cookie name?
-   *
-   * @param name The string to test.
-   * @return True only if the given string can be used as a cookie's name.
-   */
-  @CheckReturnValue
-  public static boolean isCookieName(String name) {
-    return !name.isEmpty()
-        && COOKIE_NAME.matchesAllOf(name)
-        && noLeadingOrTrailingWhitespace(name);
-  }
-
-  /**
-   * Is the given string a valid cookie value?
-   *
-   * @param value The string to test.
-   * @return True only if the given string can be used as a cookie's value.
-   */
-  @CheckReturnValue
-  public static boolean isCookieValue(String value) {
-    return value.isEmpty()
-        || (COOKIE_VALUE.matchesAllOf(value)
-            && noLeadingOrTrailingWhitespace(value));
-  }
-
-  private static boolean noLeadingOrTrailingWhitespace(String string) {
-    return !WSP.matches(string.charAt(0))
-        && !WSP.matches(string.charAt(string.length() - 1));
-  }
-
-  // **************** Date parser ****************
-
-  @VisibleForTesting
-  static long parseDate(String string) {
-    int[] hms = null;
-    int dayOfMonth = -1;
-    int month = -1;
-    int year = -1;
-    for (String token : tokenizeDate(string)) {
-      if (hms == null) {
-        hms = parseTimeToken(token);
-        if (hms != null) {
-          continue;
-        }
-      }
-      if (dayOfMonth < 0) {
-        dayOfMonth = parseDayOfMonthToken(token);
-        if (dayOfMonth >= 0) {
-          continue;
-        }
-      }
-      if (month < 0) {
-        month = parseMonthToken(token);
-        if (month >= 0) {
-          continue;
-        }
-      }
-      if (year < 0) {
-        year = parseYearToken(token);
-      }
-    }
-    if (year >= 0 && year < 70) {
-      year += 2000;
-    } else if (year >= 70 && year < 100) {
-      year += 1900;
-    }
-    String message = null;
-    if (hms == null) {
-      message = "no time seen";
-    } else if (hms[0] > 23) {
-      message = String.format("hour too large: %d", hms[0]);
-    } else if (hms[1] > 59) {
-      message = String.format("minute too large: %d", hms[1]);
-    } else if (hms[2] > 59) {
-      message = String.format("second too large: %d", hms[2]);
-    } else if (dayOfMonth < 0) {
-      message = "no day of month seen";
-    } else if (dayOfMonth == 0 || dayOfMonth > 31) {
-      message = String.format("illegal day of month: %d", dayOfMonth);
-    } else if (month < 0) {
-      message = "no month seen";
-    } else if (year < 0) {
-      message = "no year seen";
-    } else if (year < 1601) {
-      message = String.format("year too small: %d", year);
-    }
-    if (message != null) {
-      throw new IllegalArgumentException(parseDateMessage(message, string));
-    }
-    Calendar calendar = Calendar.getInstance(GMT, Locale.US);
-    calendar.setLenient(false);
-    calendar.set(year, month, dayOfMonth, hms[0], hms[1], hms[2]);
-    try {
-      return calendar.getTimeInMillis();
-    } catch (IllegalArgumentException e) {
-      throw new IllegalArgumentException(parseDateMessage(e.getMessage(), string));
-    }
-  }
-
-  private static List<String> tokenizeDate(String string) {
-    ImmutableList.Builder<String> listBuilder = ImmutableList.builder();
-    StringBuilder tokenBuilder = null;
-    for (int i = 0; i < string.length(); i += 1) {
-      char c = string.charAt(i);
-      if (DATE_DELIMITER.matches(c)) {
-        if (tokenBuilder != null) {
-          listBuilder.add(tokenBuilder.toString());
-          tokenBuilder = null;
-        }
-      } else {
-        if (tokenBuilder == null) {
-          tokenBuilder = new StringBuilder();
-        }
-        tokenBuilder.append(c);
-      }
-    }
-    if (tokenBuilder != null) {
-      listBuilder.add(tokenBuilder.toString());
-    }
-    return listBuilder.build();
-  }
-
-  private static final CharMatcher DATE_DELIMITER =
-      CharMatcher.is('\t')
-      .or(CharMatcher.inRange('\u0020', '\u002F'))
-      .or(CharMatcher.inRange('\u003B', '\u0040'))
-      .or(CharMatcher.inRange('\u005B', '\u0060'))
-      .or(CharMatcher.inRange('\u007B', '\u007E'));
-
-  private static int[] parseTimeToken(String token) {
-    Matcher m = applyPattern(TIME_PATTERN, token);
-    if (m == null) {
-      return null;
-    }
-    int[] hms = new int[3];
-    hms[0] = Integer.valueOf(m.group(1));
-    hms[1] = Integer.valueOf(m.group(2));
-    hms[2] = Integer.valueOf(m.group(3));
-    return hms;
-  }
-
-  private static final Pattern TIME_PATTERN =
-      Pattern.compile("([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})");
-
-  private static int parseDayOfMonthToken(String token) {
-    Matcher m = applyPattern(DAY_OF_MONTH_PATTERN, token);
-    return (m != null) ? Integer.valueOf(m.group()) : -1;
-  }
-
-  private static final Pattern DAY_OF_MONTH_PATTERN = Pattern.compile("[0-9]{1,2}");
-
-  private static int parseMonthToken(String token) {
-    if (token.length() < 3) {
-      return -1;
-    }
-    String p = token.substring(0, 3);
-    for (Map.Entry<String, Integer> entry : MONTHS.entrySet()) {
-      if (entry.getKey().equalsIgnoreCase(p)) {
-        return entry.getValue();
-      }
-    }
-    return -1;
-  }
-
-  private static final Map<String, Integer> MONTHS;
-  static {
-    ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
-    builder.put("jan", Calendar.JANUARY);
-    builder.put("feb", Calendar.FEBRUARY);
-    builder.put("mar", Calendar.MARCH);
-    builder.put("apr", Calendar.APRIL);
-    builder.put("may", Calendar.MAY);
-    builder.put("jun", Calendar.JUNE);
-    builder.put("jul", Calendar.JULY);
-    builder.put("aug", Calendar.AUGUST);
-    builder.put("sep", Calendar.SEPTEMBER);
-    builder.put("oct", Calendar.OCTOBER);
-    builder.put("nov", Calendar.NOVEMBER);
-    builder.put("dec", Calendar.DECEMBER);
-    MONTHS = builder.build();
-  }
-
-  private static int parseYearToken(String token) {
-    Matcher m = applyPattern(YEAR_PATTERN, token);
-    return (m != null) ? Integer.valueOf(m.group()) : -1;
-  }
-
-  private static final Pattern YEAR_PATTERN = Pattern.compile("[0-9]{2,4}");
-
-  private static Matcher applyPattern(Pattern pattern, String token) {
-    Matcher m = pattern.matcher(token);
-    if (m.lookingAt()) {
-      int end = m.end();
-      if (end == token.length() || !HttpUtil.DIGIT.matches(token.charAt(end))) {
-        return m;
-      }
-    }
-    return null;
-  }
-
-  private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
-
-  private static String parseDateMessage(String message, String string) {
-    return String.format("Can't parse date string because %s: %s",
-        message, Stringify.object(string));
-  }
-
-  // **************** Constructor ****************
-
-  /**
-   * Gets a {@link GCookie} with just a name and a value.
-   *
-   * @param name The name of the cookie to build.
-   * @param value The value of the cookie to build.
-   * @return A {@link GCookie}.
-   * @throws IllegalArgumentException if {@code name} doesn't satisfy
-   *     {@link #isCookieName} or if {@code value} doesn't satisfy
-   *     {@link #isCookieValue}.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static GCookie make(String name, String value) {
-    return builder(name).setValue(value).build();
-  }
-
-  /**
-   * Gets a builder for constructing a {@link GCookie}.
-   *
-   * @param name The name of the cookie to build.
-   * @return A {@link GCookie} builder.
-   * @throws IllegalArgumentException if {@code name} doesn't satisfy
-   *     {@link #isCookieName}.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Builder builder(String name) {
-    return new Builder(name, DateTimeUtils.currentTimeMillis());
-  }
-
-  /**
-   * Gets a builder for constructing a {@link GCookie}.
-   *
-   * @param name The name of the cookie to build.
-   * @param now The current time in milliseconds since the epoch.
-   * @return A {@link GCookie} builder.
-   * @throws IllegalArgumentException if {@code name} doesn't satisfy
-   *     {@link #isCookieName} or if {@code now} is negative.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Builder builder(String name, long now) {
-    return new Builder(name, now);
-  }
-
-  /**
-   * Gets a builder for constructing a {@link GCookie}.
-   *
-   * @param key The key of the cookie to build.
-   * @return A {@link GCookie} builder.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Builder builder(Key key) {
-    return builder(key.getName())
-        .setDomain(key.getDomain())
-        .setPath(key.getPath());
-  }
-
-  /**
-   * Gets a builder for constructing a {@link GCookie}.
-   *
-   * @param cookie A cookie to use to pre-populate the builder.
-   * @return A {@link GCookie} builder.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Builder builder(Cookie cookie) {
-    return builder(cookie.getName()).setFromCookie(cookie);
-  }
-
-  /**
-   * Gets a builder for constructing a {@link GCookie}.
-   *
-   * @param cookie A cookie to use to pre-populate the builder.
-   * @return A {@link GCookie} builder.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Builder builder(GCookie cookie) {
-    return builder(cookie.getName()).setFromCookie(cookie);
-  }
-
-  /**
-   * A builder class for {@link GCookie} instances.
-   */
-  @NotThreadSafe
-  @ParametersAreNonnullByDefault
-  public static final class Builder {
-    @Nonnull private final String name;
-    @Nonnegative private final long now;
-    @Nonnull private String value = "";
-    private long expires = -1;
-    @Nonnull private String domain = "";
-    @Nonnull private String path = "";
-    private long creationTime = -1;
-    private long lastAccessTime = -1;
-    private boolean persistent = false;
-    private boolean hostOnly = false;
-    private boolean secureOnly = false;
-    private boolean httpOnly = false;
-    private boolean maxAgeSet = false;
-    private long maxAge;
-
-    private Builder(String name, @Nonnegative long now) {
-      Preconditions.checkArgument(isCookieName(name),
-          "Illegal name: %s", name);
-      Preconditions.checkArgument(now >= 0,
-          "Illegal time: %s", now);
-      this.name = name;
-      this.now = now;
-    }
-
-    /**
-     * Builds the cookie using the parameters accumulated by the builder.
-     *
-     * @return A newly created {@link GCookie}.
-     */
-    @CheckReturnValue
-    @Nonnull
-    public GCookie build() {
-      long at = computeLastAccessTime();
-      long ct = computeCreationTime(at);
-      return new GCookie(new Key(name, domain, path), value, computeExpires(ct), ct, at,
-          computePersistent(), hostOnly, secureOnly, httpOnly);
-    }
-
-    // The following computations assume that:
-    // 1. If maxAgeSet is true, maxAge is preferred to expires and persistent.
-    // 2. creationTime is either negative or <= now.
-    // 3. lastAccessTime is either negative or <= now.
-    // 4. When finished, creationTime <= lastAccessTime.
-
-    private long computeLastAccessTime() {
-      return (lastAccessTime < 0) ? now : lastAccessTime;
-    }
-
-    private long computeCreationTime(long lastAccessTime) {
-      return (creationTime < 0 || lastAccessTime < creationTime)
-          ? lastAccessTime
-          : creationTime;
-    }
-
-    private long computeExpires(long creationTime) {
-      return maxAgeSet
-          ? ((maxAge < 0) ? Long.MAX_VALUE : creationTime + (maxAge * 1000))
-          : ((expires < 0) ? Long.MAX_VALUE : expires);
-    }
-
-    private boolean computePersistent() {
-      return maxAgeSet ? (maxAge >= 0) : persistent;
-    }
-
-    /**
-     * Sets the value of the {@link GCookie} being built.
-     *
-     * @param value The value.
-     * @return This builder, for convenience.
-     * @throws IllegalArgumentException if {@code value} doesn't satisfy
-     *     {@link #isCookieValue}.
-     */
-    @Nonnull
-    public Builder setValue(String value) {
-      Preconditions.checkArgument(isCookieValue(value),
-          "Illegal value: %s", value);
-      this.value = value;
-      return this;
-    }
-
-    /**
-     * Sets the expiration time of the {@link GCookie} being built.
-     *
-     * @param expires The expiration time.
-     * @return This builder, for convenience.
-     * @throws IllegalArgumentException if the argument is invalid.
-     */
-    @Nonnull
-    public Builder setExpires(@Nonnegative long expires) {
-      Preconditions.checkArgument(expires >= 0,
-          "Illegal expires: %s", expires);
-      this.expires = expires;
-      return this;
-    }
-
-    /**
-     * Sets the maximum age of the {@link GCookie} being built.  Translates this
-     * age into the "expires" and "persistent" attributes of the resulting
-     * cookie.
-     *
-     * @param maxAge The maximum age in seconds.
-     * @return This builder, for convenience.
-     */
-    @Nonnull
-    public Builder setMaxAge(long maxAge) {
-      this.maxAge = maxAge;
-      maxAgeSet = true;
-      return this;
-    }
-
-    /**
-     * Sets the domain of the {@link GCookie} being built.
-     *
-     * @param domain The domain.
-     * @return This builder, for convenience.
-     */
-    @Nonnull
-    public Builder setDomain(String domain) {
-      this.domain = canonicalizeDomain(domain);
-      return this;
-    }
-
-    /**
-     * Sets the path of the {@link GCookie} being built.
-     *
-     * @param path The path.
-     * @return This builder, for convenience.
-     * @throws IllegalArgumentException if the argument is invalid.
-     */
-    @Nonnull
-    public Builder setPath(String path) {
-      Preconditions.checkArgument(path.isEmpty() || firstChar(path) == PATH_SEPARATOR,
-          "Illegal path: %s", path);
-      this.path = path;
-      return this;
-    }
-
-    /**
-     * Sets the creation time of the {@link GCookie} being built.
-     *
-     * @param creationTime The creation time.
-     * @return This builder, for convenience.
-     * @throws IllegalArgumentException if the argument is invalid.
-     */
-    @Nonnull
-    public Builder setCreationTime(@Nonnegative long creationTime) {
-      Preconditions.checkArgument(creationTime >= 0 && creationTime <= now,
-          "Illegal creation time: %s", creationTime);
-      this.creationTime = creationTime;
-      return this;
-    }
-
-    /**
-     * Sets the last-access time of the {@link GCookie} being built.
-     *
-     * @param lastAccessTime The last-access time.
-     * @return This builder, for convenience.
-     * @throws IllegalArgumentException if the argument is invalid.
-     */
-    @Nonnull
-    public Builder setLastAccessTime(@Nonnegative long lastAccessTime) {
-      Preconditions.checkArgument(lastAccessTime >= 0 && lastAccessTime <= now,
-          "Illegal last-access time: %s", lastAccessTime);
-      this.lastAccessTime = lastAccessTime;
-      return this;
-    }
-
-    /**
-     * Sets whether the {@link GCookie} being built is persistent.
-     *
-     * @param persistent True if the cookie is persistent.
-     * @return This builder, for convenience.
-     */
-    @Nonnull
-    public Builder setPersistent(boolean persistent) {
-      this.persistent = persistent;
-      return this;
-    }
-
-    /**
-     * Sets whether the {@link GCookie} being built is restricted to "secure"
-     * connections.
-     *
-     * @param secureOnly True if the cookie is restricted.
-     * @return This builder, for convenience.
-     */
-    @Nonnull
-    public Builder setSecureOnly(boolean secureOnly) {
-      this.secureOnly = secureOnly;
-      return this;
-    }
-
-    /**
-     * Sets whether the {@link GCookie} being built is restricted to the host
-     * that exactly matches its domain.
-     *
-     * @param hostOnly True if the cookie is restricted.
-     * @return This builder, for convenience.
-     */
-    @Nonnull
-    public Builder setHostOnly(boolean hostOnly) {
-      this.hostOnly = hostOnly;
-      return this;
-    }
-
-    /**
-     * Sets whether the {@link GCookie} being built should be restricted to the
-     * HTTP messages.  In other words, if true, Javascript client programs can't
-     * access this cookie.
-     *
-     * @param httpOnly If true, the cookie should be restricted.
-     * @return This builder, for convenience.
-     */
-    @Nonnull
-    public Builder setHttpOnly(boolean httpOnly) {
-      this.httpOnly = httpOnly;
-      return this;
-    }
-
-    /**
-     * Sets the fields of the {@link GCookie} being built by copying them from a
-     * given cookie.  All fields in the given cookie, other than the name and
-     * value, are copied to the new {@link GCookie}.
-     *
-     * @param cookie The cookie to copy them from.
-     * @return This builder, for convenience.
-     */
-    @Nonnull
-    public Builder setFromCookie(Cookie cookie) {
-      setValue(cookie.getValue());
-      setMaxAge(cookie.getMaxAge());
-      setDomain(cookie.getDomain());
-      setPath(cookie.getPath());
-      setSecureOnly(cookie.getSecure());
-      return this;
-    }
-
-    /**
-     * Sets the fields of the {@link GCookie} being built by copying them from a
-     * given cookie.  All fields in the given cookie, other than the name and
-     * value, are copied to the new {@link GCookie}.
-     *
-     * @param cookie The cookie to copy them from.
-     * @return This builder, for convenience.
-     */
-    @Nonnull
-    public Builder setFromCookie(GCookie cookie) {
-      setValue(cookie.getValue());
-      setExpires(cookie.getExpires());
-      setDomain(cookie.getDomain());
-      setPath(cookie.getPath());
-      setCreationTime(cookie.getCreationTime());
-      setLastAccessTime(cookie.getLastAccessTime());
-      setPersistent(cookie.getPersistent());
-      setHostOnly(cookie.getHostOnly());
-      setSecureOnly(cookie.getSecureOnly());
-      setHttpOnly(cookie.getHttpOnly());
-      return this;
-    }
-  }
-
-  // **************** Interface with HTTP request/response ****************
-
-  /**
-   * Parses cookies from the headers of an HTTP request.
-   *
-   * @param request The request to get the headers from.
-   * @param sessionId A session ID to add to log messages.
-   * @param store A cookie store to which the parsed cookies will be added.
-   */
-  public static void parseHttpRequestCookies(HttpServletRequest request, String sessionId,
-      CookieStore store) {
-    parseRequestHeaders(
-        HttpUtil.getRequestHeaderValues(HttpUtil.HTTP_HEADER_COOKIE, request),
-        HttpUtil.getRequestUri(request, false),
-        sessionId,
-        store);
-  }
-
-  /**
-   * Parses cookies from the headers of an HTTP request.
-   *
-   * @param request The request to get the headers from.
-   * @param sessionId A session ID to add to log messages.
-   * @return A cookie store containing the parsed cookies.
-   */
-  public static CookieStore parseHttpRequestCookies(HttpServletRequest request, String sessionId) {
-    CookieStore store = makeStore();
-    parseHttpRequestCookies(request, sessionId, store);
-    return store;
-  }
-
-  /**
-   * Adds a cookie to an HTTP response.
-   *
-   * @param cookie The cookie to add.
-   * @param response The response to save the cookie header in.
-   */
-  public static void addHttpResponseCookie(GCookie cookie, HttpServletResponse response) {
-    response.addCookie(cookie.toCookie());
-    response.addHeader(HttpUtil.HTTP_HEADER_SET_COOKIE, cookie.responseHeaderString(true));
-  }
-
-  /**
-   * Adds cookies to an HTTP response.
-   *
-   * @param cookies The cookies to add.
-   * @param response The response to save the cookie headers in.
-   */
-  public static void addHttpResponseCookies(Iterable<GCookie> cookies,
-      HttpServletResponse response) {
-    for (GCookie cookie : cookies) {
-      addHttpResponseCookie(cookie, response);
-    }
-  }
-
-  // **************** JSON ****************
-
-  public static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(GCookie.class,
-        ProxyTypeAdapter.make(GCookie.class, GCookie.LocalProxy.class));
-  }
-
-  private static final class LocalProxy implements TypeProxy<GCookie> {
-    String name;
-    String value;
-    long expires;
-    String domain;
-    String path;
-    long creationTime;
-    long lastAccessTime;
-    boolean persistent;
-    boolean hostOnly;
-    boolean secureOnly;
-    boolean httpOnly;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(GCookie cookie) {
-      name = cookie.getName();
-      value = cookie.getValue();
-      expires = cookie.getExpires();
-      domain = cookie.getDomain();
-      path = cookie.getPath();
-      creationTime = cookie.getCreationTime();
-      lastAccessTime = cookie.getLastAccessTime();
-      persistent = cookie.getPersistent();
-      hostOnly = cookie.getHostOnly();
-      secureOnly = cookie.getSecureOnly();
-      httpOnly = cookie.getHttpOnly();
-    }
-
-    @Override
-    public GCookie build() {
-      return builder(name)
-          .setValue(value)
-          .setExpires(expires)
-          .setDomain(domain)
-          .setPath(path)
-          .setCreationTime(creationTime)
-          .setLastAccessTime(lastAccessTime)
-          .setPersistent(persistent)
-          .setHostOnly(hostOnly)
-          .setSecureOnly(secureOnly)
-          .setHttpOnly(httpOnly)
-          .build();
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/common/HttpUtil.java b/src/com/google/enterprise/secmgr/common/HttpUtil.java
deleted file mode 100644
index 0aab54c..0000000
--- a/src/com/google/enterprise/secmgr/common/HttpUtil.java
+++ /dev/null
@@ -1,825 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.common;
-
-import com.google.common.base.CharMatcher;
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Multimap;
-
-import org.springframework.mock.web.MockHttpServletRequest;
-
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * Static methods for fetching pages via HTTP.  See RFCs 2616 and 2617 for
- * details.
- */
-public final class HttpUtil {
-
-  public static final String HTTP_METHOD_GET = "GET";
-  public static final String HTTP_METHOD_POST = "POST";
-  public static final String HTTP_METHOD_HEAD = "HEAD";
-
-  // HTTP header names.
-  public static final String HTTP_HEADER_ACCEPT = "Accept";
-  public static final String HTTP_HEADER_ACCEPT_CHARSET = "Accept-Charset";
-  public static final String HTTP_HEADER_ACCEPT_ENCODING = "Accept-Encoding";
-  public static final String HTTP_HEADER_ACCEPT_LANGUAGE = "Accept-Language";
-  public static final String HTTP_HEADER_AUTHORIZATION = "Authorization";
-  public static final String HTTP_HEADER_CONNECTION = "Connection";
-  public static final String HTTP_HEADER_CONTENT_LENGTH = "Content-Length";
-  public static final String HTTP_HEADER_COOKIE = "Cookie";
-  public static final String HTTP_HEADER_DATE = "Date";
-  public static final String HTTP_HEADER_LOCATION = "Location";
-  public static final String HTTP_HEADER_PROXY_AUTHENTICATE = "Proxy-Authenticate";
-  public static final String HTTP_HEADER_PROXY_AUTHORIZATION = "Proxy-Authorization";
-  public static final String HTTP_HEADER_RANGE = "Range";
-  public static final String HTTP_HEADER_SET_COOKIE = "Set-Cookie";
-  public static final String HTTP_HEADER_SET_COOKIE2 = "Set-Cookie2";
-  public static final String HTTP_HEADER_USER_AGENT = "User-Agent";
-  public static final String HTTP_HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
-
-  // TODO(kstillson): The rest of this file is general purpose http, but
-  // this cookie-cracking code is quite security manager specific.  At some
-  // point, it would be good to refactor (perhaps providing a caller
-  // specified callback for custom header processing?)
-  //
-  // TODO(kstillson): make this extensible/configurable (at least from spring).
-  // These are Google-specific headers set in a response, which can set the
-  // username and groups list for a credentials group.
-  public static final String COOKIE_CRACK_USERNAME_HEADER = "X-Username";
-  public static final String COOKIE_CRACK_GROUPS_HEADER = "X-Groups";
-
-  // Boilerplate HTTP header values.
-  public static final String KEEP_ALIVE = "keep-alive";
-  // TODO(michellez): make this configurable through spring.
-  public static final String USER_AGENT = "SecMgr";
-  public static final String ACCEPT =
-      "text/html, text/xhtml;q=0.9, text/plain;q=0.5, text/*;q=0.1";
-  public static final String ACCEPT_FOR_HEAD = "*/*";
-  public static final String ACCEPT_CHARSET = "us-ascii, iso-8859-1, utf-8";
-  public static final String ACCEPT_ENCODING = "identity";
-  public static final String ACCEPT_LANGUAGE = "en-us, en;q=0.9";
-  private static final String RANGE_FORMAT = "bytes=0-%d";
-
-  public static final char PARAM_VALUE_SEPARATOR = '=';
-  public static final char STRING_DELIMITER = '"';
-  public static final char STRING_QUOTE = '\\';
-  public static final char PARAM_SEPARATOR_CHAR = ';';
-  public static final String PARAM_SEPARATOR = "; ";
-
-  // Don't instantiate.
-  private HttpUtil() {
-    throw new UnsupportedOperationException();
-  }
-
-  public static boolean isHttpGetMethod(String method) {
-    return HTTP_METHOD_GET.equalsIgnoreCase(method);
-  }
-
-  public static boolean isHttpPostMethod(String method) {
-    return HTTP_METHOD_POST.equalsIgnoreCase(method);
-  }
-
-  public static boolean isHttpHeadMethod(String method) {
-    return HTTP_METHOD_HEAD.equalsIgnoreCase(method);
-  }
-
-  /*
-  // Commented out to prevent pulling in ServletBase.
-  public static List<StringPair> getBoilerplateHeaders() {
-    return getBoilerplateHeaders(false);
-  }
-
-  public static List<StringPair> getBoilerplateHeaders(boolean isHeadRequest) {
-    String accept = isHeadRequest ? ACCEPT_FOR_HEAD : ACCEPT;
-    return ImmutableList.of(
-        new StringPair(HTTP_HEADER_ACCEPT, accept),
-        new StringPair(HTTP_HEADER_ACCEPT_CHARSET, ACCEPT_CHARSET),
-        new StringPair(HTTP_HEADER_ACCEPT_ENCODING, ACCEPT_ENCODING),
-        new StringPair(HTTP_HEADER_ACCEPT_LANGUAGE, ACCEPT_LANGUAGE),
-        new StringPair(HTTP_HEADER_DATE, ServletBase.httpDateString()));
-  }*/
-
-  /**
-   * Does the given HTTP status code indicate a valid response?
-   *
-   * @param status The status code to test.
-   * @return True only if it indicates a valid response.
-   */
-  public static boolean isGoodHttpStatus(int status) {
-    return status == HttpServletResponse.SC_OK
-        || status == HttpServletResponse.SC_PARTIAL_CONTENT;
-  }
-
-  public static URL urlFromString(String urlString) {
-    try {
-      return new URL(urlString);
-    } catch (MalformedURLException e) {
-      throw new IllegalArgumentException(e);
-    }
-  }
-
-  public static URL urlFromString(URL baseUrl, String urlString) {
-    try {
-      return new URL(baseUrl, urlString);
-    } catch (MalformedURLException e) {
-      throw new IllegalArgumentException(e);
-    }
-  }
-
-  public static URL urlFromParts(String protocol, String host, int port, String file) {
-    try {
-      return new URL(protocol, host, port, file);
-    } catch (MalformedURLException e) {
-      throw new IllegalArgumentException(e);
-    }
-  }
-
-  public static URL parseUrlString(String urlString) {
-    try {
-      return new URL(urlString);
-    } catch (MalformedURLException e) {
-      return null;
-    }
-  }
-
-  public static URL parseUrlString(URL baseUrl, String urlString) {
-    try {
-      return new URL(baseUrl, urlString);
-    } catch (MalformedURLException e) {
-      return null;
-    }
-  }
-
-  public static URL parentUrl(URL url) {
-    String path = url.getPath();
-    int slash = path.lastIndexOf('/');
-    if (slash <= 0) {
-      return null;
-    }
-    return urlFromParts(url.getProtocol(), url.getHost(), url.getPort(), path.substring(0, slash));
-  }
-
-  public static URL stripQueryFromUrl(URL url) {
-    return mergeQueryIntoUrl(url, null);
-  }
-
-  public static URL mergeQueryIntoUrl(URL url, String query) {
-    return urlFromParts(url.getProtocol(), url.getHost(), url.getPort(),
-        newQuery(url.getPath(), query));
-  }
-
-  private static String newQuery(String path, String query) {
-    return Strings.isNullOrEmpty(query) ? path : path + "?" + query;
-  }
-
-  /**
-   * Converts a {@link URL} to a {@link URI}.
-   *
-   * @param url The URL to convert.
-   * @return The corresponding URI.
-   * @throws IllegalArgumentException if there are any parse errors in the
-   *     conversion.
-   */
-  public static URI toUri(URL url) {
-    return URI.create(url.toString());
-  }
-
-  /**
-   * Takes a given URI and returns a new one in which the query component has
-   * been replaced with a given query string.
-   *
-   * @param uri The base URI.
-   * @param query The new query component; may be {@code null} to delete the
-   *     query component.
-   * @return A suitably modified URI.
-   */
-  public static URI replaceUriQuery(URI uri, String query) {
-    try {
-      return new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(),
-          uri.getPath(), query, uri.getFragment());
-    } catch (URISyntaxException e) {
-      throw new IllegalArgumentException(e);
-    }
-  }
-
-  /**
-   * Decodes an application/x-www-form-urlencoded format query string into its
-   * component parameters.
-   *
-   * @param uri A URI to decode the query string of.
-   * @return A multimap containing the decoded parameters from the uri.
-   * @throws IllegalArgumentException if the URI's query isn't correctly formatted.
-   */
-  public static ListMultimap<String, String> decodeQueryString(URI uri) {
-    return decodeQueryString(uri.getQuery());
-  }
-
-  /**
-   * Decodes an application/x-www-form-urlencoded format query string into its
-   * component parameters.
-   *
-   * @param string The query string to decode.
-   * @return A multimap containing the decoded parameters from the string.
-   * @throws IllegalArgumentException if the string isn't correctly formatted.
-   */
-  public static ListMultimap<String, String> decodeQueryString(String string) {
-    ListMultimap<String, String> result = ArrayListMultimap.create();
-    if (!Strings.isNullOrEmpty(string)) {
-      for (String element : QUERY_SPLITTER.split(string)) {
-        int index = element.indexOf('=');
-        if (index < 0) {
-          result.put(element, null);
-        } else {
-          result.put(element.substring(0, index), element.substring(index + 1));
-        }
-      }
-    }
-    return result;
-  }
-
-  /**
-   * Encodes a multimap of query parameters in application/x-www-form-urlencoded
-   * format.
-   *
-   * @param parameters The query parameters to be encoded.
-   * @return The encoded string.
-   */
-  public static String encodeQueryString(Multimap<String, String> parameters) {
-    StringBuilder builder = new StringBuilder();
-    boolean needSeparator = false;
-    for (Map.Entry<String, String> entry : parameters.entries()) {
-      if (needSeparator) {
-        builder.append('&');
-      } else {
-        needSeparator = true;
-      }
-      builder.append(entry.getKey());
-      if (entry.getValue() != null) {
-        builder.append('=');
-        builder.append(entry.getValue());
-      }
-    }
-    return builder.toString();
-  }
-
-  private static final Splitter QUERY_SPLITTER = Splitter.on('&');
-
-  /**
-   * Gets the URI for an HTTP request.
-   *
-   * @param request The HTTP request to get the URI from.
-   * @param includeQuery If true, include the query part of the URI.
-   * @return The request URI.
-   * @throws IllegalArgumentException if the request's URI can't be parsed.
-   */
-  public static URI getRequestUri(HttpServletRequest request, boolean includeQuery) {
-    URI uri = (request instanceof MockHttpServletRequest)
-        ? getMockRequestUri((MockHttpServletRequest) request)
-        : URI.create(request.getRequestURL().toString());
-    return includeQuery
-        ? uri
-        : replaceUriQuery(uri, null);
-  }
-
-  private static URI getMockRequestUri(MockHttpServletRequest request) {
-    // Note that it's not OK to call request.getRequestURL() because the mock
-    // implementation is broken and will include ":-1" if there's no port
-    // specified.
-    try {
-      return new URI(request.getScheme(), null, request.getServerName(), request.getServerPort(),
-          request.getRequestURI(), request.getQueryString(), null);
-    } catch (URISyntaxException e) {
-      throw new IllegalArgumentException(e);
-    }
-  }
-
-  /**
-   * Gets the URL for an HTTP request.
-   *
-   * @param request The HTTP request to get the URL from.
-   * @param includeQuery If true, include the query part of the URL.
-   * @return The request URL.
-   * @throws IllegalArgumentException if the request's URL can't be parsed.
-   */
-  public static URL getRequestUrl(HttpServletRequest request, boolean includeQuery) {
-    try {
-      return getRequestUri(request, includeQuery).toURL();
-    } catch (MalformedURLException e) {
-      throw new IllegalArgumentException(e);
-    }
-  }
-
-  /**
-   * Given a URL, gets a string suitable for logging.  This string omits the URL
-   * query, as it might contain sensitive parameters that shouldn't be logged
-   * (e.g. a password).  It also omits the fragment identifier, since that isn't
-   * usually needed in the log.
-   *
-   * @param url The URL to get a log string for.
-   * @return An appropriate string representation of the URL.
-   */
-  public static String getUrlLogString(URL url) {
-    return getUriLogString(toUri(url));
-  }
-
-  /**
-   * Given a URL string, gets a string suitable for logging.  This string omits
-   * the URL query, as it might contain sensitive parameters that shouldn't be
-   * logged (e.g. a password).  It also omits the fragment identifier, since
-   * that isn't usually needed in the log.
-   *
-   * @param urlString The URL string to get a log string for.
-   * @return An appropriate string representation of the URL.
-   */
-  public static String getUrlLogString(String urlString) {
-    URI uri;
-    try {
-      uri = new URI(urlString);
-    } catch (URISyntaxException e) {
-      // Dumb, but in the unlikely event we get the exception, it should serve.
-      int index = urlString.indexOf('?');
-      return (index >= 0)
-          ? urlString.substring(0, index)
-          : urlString;
-    }
-    return getUriLogString(uri);
-  }
-
-  /**
-   * Given a URI, gets a string suitable for logging.  This string omits the URI
-   * query, as it might contain sensitive parameters that shouldn't be logged
-   * (e.g. a password).  It also omits the fragment identifier, since that isn't
-   * usually needed in the log.
-   *
-   * @param uri The URI to get a log string for.
-   * @return An appropriate string representation of the URL.
-   */
-  public static String getUriLogString(URI uri) {
-    try {
-      return (new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), null, null))
-          .toASCIIString();
-    } catch (URISyntaxException e) {
-      throw new IllegalArgumentException(e);
-    }
-  }
-
-  /**
-   * Gets the header value strings for any headers matching a given name.
-   *
-   * @param name The header name to look for.
-   * @param request The request to look in.
-   * @return The header values as an immutable list.
-   */
-  public static ImmutableList<String> getRequestHeaderValues(String name,
-      HttpServletRequest request) {
-    ImmutableList.Builder<String> builder = ImmutableList.builder();
-    Enumeration<?> e = request.getHeaders(name);
-    while (e.hasMoreElements()) {
-      builder.add(String.class.cast(e.nextElement()));
-    }
-    return builder.build();
-  }
-
-  /**
-   * Parse an HTTP header parameter.  Parameters come in two forms:
-   *
-   * token PARAM_VALUE_SEPARATOR token
-   * token PARAM_VALUE_SEPARATOR quoted-string
-   *
-   * The character set for a "token" is restricted.  A "quoted-string" is
-   * surrounded by double quotes and can contain nearly all characters, plus
-   * escaped characters.
-   *
-   * @param string The raw parameter string, assumed to have been trimmed of whitespace.
-   * @return A list of two strings, the name and the value.
-   * @throws IllegalArgumentException if the string can't be parsed.
-   */
-  public static List<String> parseHttpParameter(String string) {
-    int equals = string.indexOf(PARAM_VALUE_SEPARATOR);
-    checkParameterArgument(equals >= 0, string);
-    String name = string.substring(0, equals);
-    checkParameterArgument(isHttpToken(name), string);
-    String rawValue = string.substring(equals + 1, string.length());
-    return ImmutableList.of(name,
-        isHttpToken(rawValue) ? rawValue : parseHttpQuotedString(rawValue));
-  }
-
-  private static void checkParameterArgument(boolean succeed, String argument) {
-    Preconditions.checkArgument(succeed, "Incorrectly formatted HTTP parameter: %s", argument);
-  }
-
-  /**
-   * Is the given string an HTTP token?
-   *
-   * @param string The string to test.
-   * @return True if the string is a valid HTTP token.
-   */
-  public static boolean isHttpToken(String string) {
-    return !Strings.isNullOrEmpty(string) && TOKEN.matchesAllOf(string);
-  }
-
-  /**
-   * Is the given string something that can be encoded as an HTTP quoted-string?
-   *
-   * @param string The string to test.
-   * @return True if the string can be encoded using the quoted-string format.
-   */
-  public static boolean isQuotedStringEncodable(String string) {
-    return string != null && TEXT.matchesAllOf(string);
-  }
-
-  /**
-   * Encodes a string so that it's suitable as an HTTP parameter value.  In
-   * other words, if the string is an HTTP token, it's self encoding.
-   * Otherwise, it is converted to the quoted-string format.
-   *
-   * @param string The string to be encoded.
-   * @return The same string encoded as an HTTP parameter value.
-   * @throws IllegalArgumentException if the given string can't be encoded.
-   */
-  public static String makeHttpParameterValueString(String string) {
-    if (isHttpToken(string)) {
-      return string;
-    }
-    StringBuilder builder = new StringBuilder();
-    writeQuotedString(string, builder);
-    return builder.toString();
-  }
-
-  /**
-   * Writes a string-valued HTTP parameter to a given string builder.  The
-   * parameter is prefixed by {@link #PARAM_SEPARATOR}.
-   *
-   * @param name The parameter name, which must satisfy {@link #isHttpToken}.
-   * @param value The parameter value, which must satisfy
-   *     {@link #isQuotedStringEncodable}.
-   * @param builder A string builder to write the parameter to.
-   * @throws IllegalArgumentException if {@code name} or {@code value} can't be
-   *     encoded.
-   */
-  public static void writeParameter(String name, String value, StringBuilder builder) {
-    writeParameterName(name, builder);
-    builder.append(PARAM_VALUE_SEPARATOR);
-    writeParameterValue(value, builder);
-  }
-
-  /**
-   * Writes a boolean-valued HTTP parameter to a given string builder.  The
-   * parameter is prefixed by {@link #PARAM_SEPARATOR}.
-   *
-   * @param name The parameter name, which must satisfy {@link #isHttpToken}.
-   * @param value The parameter value.
-   * @param builder A string builder to write the parameter to.
-   * @throws IllegalArgumentException if {@code name} can't be encoded.
-   */
-  public static void writeParameter(String name, boolean value, StringBuilder builder) {
-    if (value) {
-      writeParameterName(name, builder);
-    }
-  }
-
-  /**
-   * Writes an HTTP parameter name to a given string builder.  The name is
-   * prefixed by {@link #PARAM_SEPARATOR}.
-   *
-   * @param name The parameter name, which must satisfy {@link #isHttpToken}.
-   * @param builder A string builder to write the name to.
-   * @throws IllegalArgumentException if {@code name} can't be encoded.
-   */
-  public static void writeParameterName(String name, StringBuilder builder) {
-    Preconditions.checkArgument(isHttpToken(name));
-    builder.append(PARAM_SEPARATOR);
-    builder.append(name);
-  }
-
-  /**
-   * Writes an HTTP parameter value to a given string builder.
-   *
-   * @param value The parameter value, which must satisfy
-   *     {@link #isQuotedStringEncodable}.
-   * @param builder A string builder to write the value to.
-   * @throws IllegalArgumentException if {@code value} can't be encoded.
-   */
-  public static void writeParameterValue(String value, StringBuilder builder) {
-    if (isHttpToken(value)) {
-      builder.append(value);
-    } else {
-      writeQuotedString(value, builder);
-    }
-  }
-
-  /**
-   * Writes a string to a string builder in HTTP quoted-string format.
-   *
-   * @param string The string to be written.
-   * @param builder A string builder to write the string to.
-   * @throws IllegalArgumentException if {@code string} can't be encoded.
-   */
-  public static void writeQuotedString(String string, StringBuilder builder) {
-    Preconditions.checkArgument(isQuotedStringEncodable(string),
-        "String can't be encoded as an HTTP parameter value: %s", string);
-    builder.append(STRING_DELIMITER);
-    for (char c : string.toCharArray()) {
-      if (c == STRING_QUOTE || c == STRING_DELIMITER) {
-        builder.append(STRING_QUOTE);
-      }
-      builder.append(c);
-    }
-    builder.append(STRING_DELIMITER);
-  }
-
-  /**
-   * Parses an HTTP quoted-string.
-   *
-   * @param string The string to parse.
-   * @return The parsed value of the quoted string.
-   * @throws IllegalArgumentException if the string isn't a valid quoted-string.
-   */
-  public static String parseHttpQuotedString(String string) {
-    int end = string.length();
-    checkQuotedStringArgument(
-        (end >= 2
-            && string.charAt(0) == STRING_DELIMITER
-            && string.charAt(end - 1) == STRING_DELIMITER),
-        string);
-    StringBuilder builder = new StringBuilder();
-    boolean pendingQuote = false;
-    for (char c : string.substring(1, end - 1).toCharArray()) {
-      if (pendingQuote) {
-        pendingQuote = false;
-        checkQuotedStringArgument(CHAR.matches(c), string);
-        builder.append(c);
-      } else if (c == STRING_QUOTE) {
-        pendingQuote = true;
-      } else {
-        checkQuotedStringArgument(QDTEXT.matches(c), string);
-        builder.append(c);
-      }
-    }
-    checkQuotedStringArgument(!pendingQuote, string);
-    return builder.toString();
-  }
-
-  /**
-   * Gets the http range header value for requesting the first number of bytes.
-   *
-   * @param bytes The number of bytes to request.
-   * @return The range header value
-   */
-  public static String getRangeString(int bytes) {
-    return String.format(RANGE_FORMAT, bytes);
-  }
-
-  private static void checkQuotedStringArgument(boolean succeed, String argument) {
-    Preconditions.checkArgument(succeed, "Incorrectly formatted quoted-string: %s", argument);
-  }
-
-  // These names are taken directly from RFC 2616.
-
-  private static final CharMatcher OCTET = CharMatcher.inRange('\u0000', '\u00ff');
-
-  // Not strictly correct: CHAR technically includes CR and LF, but only for
-  // line folding.  Since we're looking at a post-line-folding string, they
-  // shouldn't be present.
-  private static final CharMatcher CHAR = difference(CharMatcher.ASCII, CharMatcher.anyOf("\n\r"));
-
-  /** ASCII control characters. */
-  public static final CharMatcher CTLS =
-      CharMatcher.inRange('\u0000', '\u001f').or(CharMatcher.is('\u007f'));
-
-  /** ASCII alphabetic characters. */
-  public static final CharMatcher ALPHA =
-      CharMatcher.anyOf("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
-
-  /** ASCII digit characters. */
-  public static final CharMatcher DIGIT = CharMatcher.anyOf("0123456789");
-
-  /** Linear white space. */
-  public static final CharMatcher LWS = CharMatcher.anyOf(" \t");
-
-  /** Plain text. */
-  public static final CharMatcher TEXT = union(difference(OCTET, CTLS), LWS);
-
-  // Text that can be included in a quoted-string without backquotes.  Note that
-  // RFC 2616 specifies only '"' as an exception, but clearly '\\' needs to be
-  // excepted as well.
-  private static final CharMatcher QDTEXT = difference(TEXT, CharMatcher.anyOf("\"\\"));
-
-  // Separator characters that aren't allowed in most places except inside
-  // quoted-strings.
-  private static final CharMatcher SEPARATORS = CharMatcher.anyOf("()<>@,;:\\\"/[]?={} \t");
-
-  // The constituent characters of a token.
-  private static final CharMatcher TOKEN = difference(CharMatcher.ASCII, union(CTLS, SEPARATORS));
-
-  private static CharMatcher union(CharMatcher m1, CharMatcher m2) {
-    return m1.or(m2);
-  }
-
-  private static CharMatcher difference(CharMatcher m1, CharMatcher m2) {
-    return m1.and(m2.negate());
-  }
-
-  // HTTP date formats (from RFC 2616):
-  //
-  // HTTP-date    = rfc1123-date | rfc850-date | asctime-date
-  // rfc1123-date = wkday "," SP date1 SP time SP "GMT"
-  // rfc850-date  = weekday "," SP date2 SP time SP "GMT"
-  // asctime-date = wkday SP date3 SP time SP 4DIGIT
-  // date1        = 2DIGIT SP month SP 4DIGIT
-  //                ; day month year (e.g., 02 Jun 1982)
-  // date2        = 2DIGIT "-" month "-" 2DIGIT
-  //                ; day-month-year (e.g., 02-Jun-82)
-  // date3        = month SP ( 2DIGIT | ( SP 1DIGIT ))
-  //                ; month day (e.g., Jun  2)
-  // time         = 2DIGIT ":" 2DIGIT ":" 2DIGIT
-  //                ; 00:00:00 - 23:59:59
-  // wkday        = "Mon" | "Tue" | "Wed"
-  //              | "Thu" | "Fri" | "Sat" | "Sun"
-  // weekday      = "Monday" | "Tuesday" | "Wednesday"
-  //              | "Thursday" | "Friday" | "Saturday" | "Sunday"
-  // month        = "Jan" | "Feb" | "Mar" | "Apr"
-  //              | "May" | "Jun" | "Jul" | "Aug"
-  //              | "Sep" | "Oct" | "Nov" | "Dec"
-
-  private static final String DATE_FORMAT_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
-  private static final String DATE_FORMAT_RFC850 = "EEEE, dd-MMM-yy HH:mm:ss zzz";
-  private static final String DATE_FORMAT_ASCTIME = "EEE MMM dd HH:mm:ss yyyy";
-
-  /**
-   * Generates an HTTP date string.
-   *
-   * @param date A date value specified as a non-negative difference from the
-   *     epoch in milliseconds.
-   * @return An HTTP date string representing that date.
-   */
-  public static String generateHttpDate(long date) {
-    return getDateFormat(DATE_FORMAT_RFC1123).format(new Date(date));
-  }
-
-  /**
-   * Parses an HTTP date string.
-   *
-   * @param dateString The string to parse.
-   * @return The difference, measured in milliseconds, between the specified
-   *     date and 1970-01-01T00:00:00Z.
-   * @throws IllegalArgumentException if the date string can't be parsed.
-   */
-  public static long parseHttpDate(String dateString) {
-    try {
-      return parseDate(DATE_FORMAT_RFC1123, dateString);
-    } catch (ParseException e) {
-      // Fall through to next format.
-    }
-    try {
-      return parseDate(DATE_FORMAT_RFC850, dateString);
-    } catch (ParseException e) {
-      // Fall through to next format.
-    }
-    try {
-      return parseDate(DATE_FORMAT_ASCTIME, dateString);
-    } catch (ParseException e) {
-      throw new IllegalArgumentException("Can't parse as HTTP date string: " + dateString);
-    }
-  }
-
-  private static long parseDate(String formatString, String dateString)
-      throws ParseException {
-    return getDateFormat(formatString).parse(dateString).getTime();
-  }
-
-  private static DateFormat getDateFormat(String formatString) {
-    DateFormat format = new SimpleDateFormat(formatString);
-    format.setCalendar(Calendar.getInstance(GMT, Locale.US));
-    return format;
-  }
-
-  private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
-
-  /**
-   * Is the given string a valid domain name?  Uses a fairly restrictive
-   * definition, corresponding to the "preferred syntax" of RFC 1034 as updated
-   * by RFC 1123.
-   *
-   * @param string The string to be tested.
-   * @return True only if the string is a valid domain name.
-   */
-  public static boolean isValidDomainName(String string) {
-    return parseDomainName(string) != null;
-  }
-
-  /**
-   * Converts a given domain name to its canonical form.  This should eventually
-   * handle IDNA names, but for now we just canonicalize case.
-   *
-   * @param domainName The domain name to convert.
-   * @return The canonical form for {@code domainName}.
-   * @throws IllegalArgumentException if {@code domainName} doesn't satisfy
-   *     {@code #isValidDomainName}.
-   */
-  public static String canonicalizeDomainName(String domainName) {
-    List<String> labels = parseDomainName(domainName);
-    Preconditions.checkArgument(labels != null, "Not a valid domain name: %s", domainName);
-    return labelsToDomanName(labels);
-  }
-
-  /**
-   * Gets the "parent domain" name of a domain name.
-   *
-   * @param domainName The domain name to get the parent domain name of.
-   * @return The parent domain name, or {@code null} if there isn't one.
-   * @throws IllegalArgumentException if {@code domainName} doesn't satisfy
-   *     {@code #isValidDomainName}.
-   */
-  public static String domainNameParent(String domainName) {
-    List<String> labels = parseDomainName(domainName);
-    Preconditions.checkArgument(labels != null, "Not a valid domain name: %s", domainName);
-    if (labels.size() < 2) {
-      return null;
-    }
-    labels.remove(0);
-    return labelsToDomanName(labels);
-  }
-
-  private static List<String> parseDomainName(String domainName) {
-    if (!(domainName.length() >= 1 && domainName.length() <= 255)) {
-      return null;
-    }
-    List<String> labels = Lists.newArrayList(DOMAIN_NAME_SPLITTER.split(domainName));
-    if (!(labels.size() >= 1 && labels.size() <= 127)) {
-      return null;
-    }
-    for (String label : labels) {
-      if (!isValidDomainLabel(label)) {
-        return null;
-      }
-    }
-    // Eliminates IPv4 addresses:
-    if (DIGIT.matchesAllOf(labels.get(labels.size() - 1))) {
-      return null;
-    }
-    return labels;
-  }
-
-  private static boolean isValidDomainLabel(String label) {
-    return label.length() >= 1
-        && label.length() <= 63
-        && DOMAIN_LABEL_CHAR.matchesAllOf(label)
-        && label.charAt(0) != '-'
-        && label.charAt(label.length() - 1) != '-';
-  }
-
-  private static String labelsToDomanName(List<String> labels) {
-    return DOMAIN_NAME_JOINER.join(
-        Iterables.transform(labels,
-            new Function<String, String>() {
-              @Override
-              public String apply(String label) {
-                return label.toLowerCase(Locale.US);
-              }
-            }));
-  }
-
-  private static final CharMatcher DOMAIN_LABEL_CHAR = ALPHA.or(DIGIT).or(CharMatcher.is('-'));
-  private static final Splitter DOMAIN_NAME_SPLITTER = Splitter.on('.');
-  private static final Joiner DOMAIN_NAME_JOINER = Joiner.on('.');
-}
diff --git a/src/com/google/enterprise/secmgr/common/SecurePasswordHasher.java b/src/com/google/enterprise/secmgr/common/SecurePasswordHasher.java
deleted file mode 100644
index 5621fa6..0000000
--- a/src/com/google/enterprise/secmgr/common/SecurePasswordHasher.java
+++ /dev/null
@@ -1,309 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.common;
-
-import com.google.common.base.Charsets;
-
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.security.spec.InvalidKeySpecException;
-import java.util.Arrays;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.crypto.KeyGenerator;
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.PBEKeySpec;
-
-/**
- * This class implements two password hashers.  One is based on the
- * PBKDF2 specification using HMAC-SHA256 as the underlying
- * primitive.  PBKDF is short for Password-Based Key Derivation
- * Function.  Requires JCE provider that implements the
- * "PBKDF2WithHmacSHA1" algorithm.  (Briefly, this algorithm and parameter
- * selection provides some protection against certain types of offline
- * password dictionary attacks.)  This algorithm is not deterministic,
- * but it allows the possibility of "verifying" a fingerprint.
- *
- * To generate fingerprints, use SecurePasswordHasher.getFingerprint().
- *
- * The other hasher is a simple MAC.  It is deterministic, but
- * the key is not saved, which means that it is not possible to
- * verify the hash later.  It is the more secure option of the two
- * because an attacker may only try to guess username/passwords by
- * querying the service while it is running.
- *
- * To generate MAC tags, user SecurePasswordHasher.getMac().
- *
- * #################################################################
- * WARNING:
- * This does not safely obfuscate weak passwords.  Only use if it
- * is absolutely necessary to store/log information about passwords,
- * and ensure that files with stored fingerprints have appropriate
- * permissions.
- * #################################################################
- *
- * Please see the RFC for more information on password hashing
- * security: http://tools.ietf.org/html/rfc2898.
- */
-public class SecurePasswordHasher {
-
-  private static final Logger LOGGER =
-      Logger.getLogger(SecurePasswordHasher.class.getName());
-
-  private static final SecureRandom prng = new SecureRandom();
-
-  private static final int kNumSeedBytes = 16;
-  private static final int kNumIterations = 1000;
-  private static final int kNumOutputBits = 128;
-  private static final String kHashAlgorithm = "PBKDF2WithHmacSHA1";
-  private static Mac mac;
-
-  static {
-    // Initialize the MAC key.
-    try {
-      KeyGenerator kg = KeyGenerator.getInstance("HmacSHA1");
-      mac = Mac.getInstance("HmacSHA1");
-      mac.init(kg.generateKey());
-    } catch (NoSuchAlgorithmException e) {
-      LOGGER.log(Level.SEVERE, "Could not initialize MAC", e);
-      mac = null;
-    } catch (InvalidKeyException e) {
-      LOGGER.log(Level.SEVERE, "Could not initialize MAC", e);
-      mac = null;
-    }
-  }
-
-  /**
-   * We don't want this class to be instantiated.
-   */
-  private SecurePasswordHasher() {
-  }
-
-  /**
-   * A container for a fingerprint specification.  From this fingerprint
-   * specification, it should be easy to verify that a given password
-   * generated the fingerprint.  Finding the password from the fingerprint
-   * should be much more difficult as long as the password was "well-chosen".
-   */
-  public static class Fingerprint {
-    private final String hash;
-    private final String seed;
-    private final String algorithm;
-    private final int iterations;
-
-    Fingerprint(String hash, String seed, String algorithm, int iterations) {
-      this.hash = hash;
-      this.seed = seed;
-      this.algorithm = algorithm;
-      this.iterations = iterations;
-    }
-
-    public String hash() {
-      return hash;
-    }
-
-    public String seed() {
-      return seed;
-    }
-
-    public String algorithm() {
-      return algorithm;
-    }
-
-    public int iterations() {
-      return iterations;
-    }
-
-    /**
-     * Parses a Fingerprint object from a string.
-     * @param fingerprint the output of toString() from a
-     * Fingerprint object
-     */
-    public static Fingerprint parseFingerprint(String fingerprint)
-        throws IllegalArgumentException {
-      String[] parts = fingerprint.split(":");
-      if (parts.length != 4) {
-        throw new IllegalArgumentException(
-            "Incorrectly formatted fingerprint: " + fingerprint);
-      }
-
-      int iterations;
-      try {
-        iterations = Integer.parseInt(parts[3]);
-      } catch (NumberFormatException e) {
-        throw new IllegalArgumentException("Could not parse number of " +
-            "iterations from fingerprint: " + fingerprint);
-      }
-
-      return new Fingerprint(parts[0], parts[1], parts[2], iterations);
-    }
-
-    @Override
-    public String toString() {
-      return hash + ":" + seed + ":" + algorithm + ":" + iterations;
-    }
-
-    @Override
-    public int hashCode() {
-      return toString().hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-      if (!(obj instanceof Fingerprint)) {
-        return false;
-      }
-      return toString().equals(((Fingerprint) obj).toString());
-    }
-  }
-
-  /**
-   * Produce a fingerprint from an input string.  This is non-deterministic
-   * and will use safe defaults for the parameters (as of 05/2009).
-   */
-  public static synchronized Fingerprint getFingerprint(String input) {
-    byte[] seed = new byte[kNumSeedBytes];
-
-    // Randomly choose a seed.
-    synchronized (prng) {
-      prng.nextBytes(seed);
-    }
-
-    byte[] hash = hashString(input, kHashAlgorithm, kNumIterations, seed);
-    return new Fingerprint(Base64.encode(hash), Base64.encode(seed),
-        kHashAlgorithm, kNumIterations);
-  }
-
-  /**
-   * Returns true iff the input is a valid producer of the given fingerprint.
-   * @param input the candidate input string
-   * @param fingerprint
-   */
-  public static boolean verifyFingerprint(String input, Fingerprint fingerprint) {
-    byte[] seedBytes;
-    try {
-      seedBytes = Base64.decode(fingerprint.seed());
-    } catch (Base64DecoderException e) {
-      LOGGER.warning("Could not base64 decode input string: " + fingerprint.seed());
-      return false;
-    }
-
-    byte[] hashBytes;
-    try {
-      hashBytes = Base64.decode(fingerprint.hash());
-    } catch (Base64DecoderException e) {
-      LOGGER.warning("Could not base64 decode input string: " + fingerprint.hash());
-      return false;
-    }
-    return Arrays.equals(hashBytes, hashString(input, fingerprint.algorithm(),
-        fingerprint.iterations(), seedBytes));
-  }
-
-  /**
-   * Returns the MAC of the combination of the username and password.
-   * The key used to MAC these messages is not saved, so this effectively
-   * erases the threat of doing off-line brute force password-guessing.
-   * If an attacker has access to the logs, they may mount an on-line
-   * attack (querying many different known username/password combos to see
-   * if they match unknown username/password MACs), but this is a much
-   * more constrained environment.
-   *
-   * This function is deterministic, however, which enables debugging by
-   * tracking that a particular username/password is being used in
-   * multiple places or tracking how frequently a user logs in, etc.
-   *
-   * @param username required so an attacker cannot easily tell if
-   * two users have the same password by looking at the logs
-   * @param password password to mac
-   */
-  public static String getMac(String username, String password) {
-    return Base64.encode(macInput(username, password));
-  }
-
-  /**
-   * Run the input string through the PBKDF with the given parameters and
-   * return the result.
-   */
-  private static byte[] hashString(String input, String algorithm,
-                            int iterations, byte[] seed) {
-
-    PBEKeySpec keySpec = new PBEKeySpec(input.toCharArray(), seed,
-                                        iterations, kNumOutputBits);
-
-    SecretKeyFactory factory;
-    try {
-      factory = SecretKeyFactory.getInstance(algorithm);
-    } catch (NoSuchAlgorithmException e) {
-      LOGGER.log(Level.SEVERE, "Could not get key spec", e);
-      return new byte[kNumSeedBytes];  // Don't reveal information about the password.
-    }
-
-    SecretKey hash;
-    try {
-      hash = factory.generateSecret(keySpec);
-    } catch (InvalidKeySpecException e) {
-      LOGGER.severe("Could not load hash algorithm: " + e);
-      return new byte[kNumSeedBytes];  // Don't reveal information about the password.
-    }
-    return hash.getEncoded();
-  }
-
-  /**
-   * Returns a one-way keyed function output for the given username and
-   * password.
-   *
-   * @param username required so an attacker cannot easily tell if two users
-   *     have the same password by looking at the logs
-   * @param password password to mac
-   */
-  public static byte[] macInput(String username, String password) {
-    if (mac == null) {
-      LOGGER.severe("tried to MAC message when mac object uninitialized");
-      return new byte[0];
-    }
-    return mac.doFinal((username + ":" + password).getBytes(Charsets.UTF_8));
-  }
-
-  /**
-   * This provides a simple command-line tool to verify passwords.
-   */
-  public static void main(String[] args) throws Throwable {
-    int numArgs = args.length;
-    if (numArgs < 2 || numArgs > 3) {
-      System.err.println("Usage: SecurePasswordHasher password [fingerprint]");
-      System.exit(1);
-    }
-    if (numArgs == 2) {
-      System.out.println(SecurePasswordHasher.getFingerprint(args[1])
-                         .toString());
-    } else {
-      Fingerprint fingerprint = Fingerprint.parseFingerprint(args[2]);
-      boolean verified =
-          SecurePasswordHasher.verifyFingerprint(args[1], fingerprint);
-      if (verified) {
-        System.out.println("Password is correct");
-      } else {
-        System.out.println("Invalid password");
-      }
-    }
-
-    System.exit(0);
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/common/SecurityManagerUtil.java b/src/com/google/enterprise/secmgr/common/SecurityManagerUtil.java
index 87bd887..395d6d3 100644
--- a/src/com/google/enterprise/secmgr/common/SecurityManagerUtil.java
+++ b/src/com/google/enterprise/secmgr/common/SecurityManagerUtil.java
@@ -15,35 +15,9 @@
 package com.google.enterprise.secmgr.common;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.BoundedExecutorService;
 
-import org.joda.time.DateTimeUtils;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.security.SecureRandom;
-import java.util.Collection;
-import java.util.Formatter;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnegative;
-import javax.annotation.Nonnull;
 import javax.annotation.concurrent.ThreadSafe;
 
 /**
@@ -59,27 +33,6 @@
   }
 
   /**
-   * Remove all elements specified by a given predicate from a collection.
-   *
-   * @param iterable The collection to modify.
-   * @param predicate The predicate identifying the elements to remove.
-   * @return A collection of the elements that were removed.
-   */
-  public static <T> Collection<T> removeInPlace(Iterable<T> iterable, Predicate<T> predicate) {
-    ImmutableList.Builder<T> builder = ImmutableList.builder();
-    Iterator<T> iterator = iterable.iterator();
-    boolean changed = false;
-    while (iterator.hasNext()) {
-      T element = iterator.next();
-      if (predicate.apply(element)) {
-        iterator.remove();
-        builder.add(element);
-      }
-    }
-    return builder.build();
-  }
-
-  /**
    * Annotate a log message with a given session ID.  This should be implemented
    * in the session manager, but can't be due to cyclic build dependencies.
    *
@@ -92,72 +45,6 @@
   }
 
   /**
-   * Generate a random nonce as a byte array.
-   *
-   * @param nBytes The number of random bytes to generate.
-   * @return A randomly generated byte array of the given length.
-   */
-  public static byte[] generateRandomNonce(int nBytes) {
-    byte[] randomBytes = new byte[nBytes];
-    synchronized (prng) {
-      prng.nextBytes(randomBytes);
-    }
-    return randomBytes;
-  }
-
-  /**
-   * Generate a random nonce as a hexadecimal string.
-   *
-   * @param nBytes The number of random bytes to generate.
-   * @return A randomly generated hexadecimal string.
-   */
-  public static String generateRandomNonceHex(int nBytes) {
-    return bytesToHex(generateRandomNonce(nBytes));
-  }
-
-  private static final SecureRandom prng = new SecureRandom();
-
-  /**
-   * Convert a byte array to a hexadecimal string.
-   *
-   * @param bytes The byte array to convert.
-   * @return The equivalent hexadecimal string.
-   */
-  public static String bytesToHex(byte[] bytes) {
-    Preconditions.checkNotNull(bytes);
-    Formatter f = new Formatter();
-    for (byte b : bytes) {
-      f.format("%02x", b);
-    }
-    return f.toString();
-  }
-
-  /**
-   * Convert a hexadecimal string to a byte array.
-   *
-   * @param hexString The hexadecimal string to convert.
-   * @return The equivalent array of bytes.
-   * @throws IllegalArgumentException if the string isn't valid hexadecimal.
-   */
-  public static byte[] hexToBytes(String hexString) {
-    Preconditions.checkNotNull(hexString);
-    int len = hexString.length();
-    Preconditions.checkArgument(len % 2 == 0);
-    int nBytes = len / 2;
-    byte[] decoded = new byte[nBytes];
-    int j = 0;
-    for (int i = 0; i < nBytes; i += 1) {
-      int d1 = Character.digit(hexString.charAt(j++), 16);
-      int d2 = Character.digit(hexString.charAt(j++), 16);
-      if (d1 < 0 || d2 < 0) {
-        throw new IllegalArgumentException("Non-hexadecimal character in string: " + hexString);
-      }
-      decoded[i] = (byte) ((d1 << 4) + d2);
-    }
-    return decoded;
-  }
-
-  /**
    * Is a given remote "before" time valid?  In other words, is it possible that
    * the remote "before" time is less than or equal to the remote "now" time?
    *
@@ -187,280 +74,4 @@
   }
 
   private static final long CLOCK_SKEW_TIME = 5000;
-
-  /**
-   * Compare two URLs for equality.  Preferable to using the {@link URL#equals}
-   * because the latter calls out to DNS and can block.
-   *
-   * @param url1 A URL to compare.
-   * @param url2 Another URL to compare.
-   * @return True if the two URLs are the same.
-   */
-  public static boolean areUrlsEqual(URL url1, URL url2) {
-    if (url1 == null || url2 == null) {
-      return url1 == null && url2 == null;
-    }
-    return areStringsEqualIgnoreCase(url1.getProtocol(), url2.getProtocol())
-        && areStringsEqualIgnoreCase(url1.getHost(), url2.getHost())
-        && url1.getPort() == url2.getPort()
-        && areStringsEqual(url1.getFile(), url2.getFile())
-        && areStringsEqual(url1.getRef(), url2.getRef());
-  }
-
-  private static boolean areStringsEqual(String s1, String s2) {
-    return s1 == s2 || ((s1 == null) ? s2 == null : s1.equals(s2));
-  }
-
-  private static boolean areStringsEqualIgnoreCase(String s1, String s2) {
-    return s1 == s2 || ((s1 == null) ? s2 == null : s1.equalsIgnoreCase(s2));
-  }
-
-  /**
-   * @return The value of ENT_CONFIG_NAME from the GSA configuration.
-   *   If not running on a GSA (e.g. for testing), return a fixed string.
-   */
-  public static String getGsaEntConfigName() {
-    String entConfigName = System.getProperty("gsa.entityid");
-    if (entConfigName == null) {
-      return "testing";
-    }
-    return entConfigName;
-  }
-
-  /**
-   * @return A URI builder with default scheme and host arguments.
-   */
-  public static UriBuilder uriBuilder() {
-    return new UriBuilder("http", "google.com");
-  }
-
-  /**
-   * @param scheme The URI Scheme to use.
-   * @param host The URI host to use.
-   * @return A URI builder with the given scheme and host.
-   */
-  public static UriBuilder uriBuilder(String scheme, String host) {
-    return new UriBuilder(scheme, host);
-  }
-
-  /**
-   * A class to build URIs by incrementally specifying their path segments.
-   */
-  public static final class UriBuilder {
-    private final String scheme;
-    private final String host;
-    private final StringBuilder pathBuilder;
-
-    private UriBuilder(String scheme, String host) {
-      this.scheme = scheme;
-      this.host = host;
-      pathBuilder = new StringBuilder();
-    }
-
-    /**
-     * Add a segment to the path being accumulated.
-     *
-     * @param segment The segment to add.
-     * @return The builder, for convenience.
-     * @throws IllegalArgumentException if the segment contains any illegal characters.
-     */
-    public UriBuilder addSegment(String segment) {
-      Preconditions.checkArgument(segment != null && !segment.contains("/"),
-          "Path segments may not contain the / character: %s", segment);
-      pathBuilder.append("/").append(segment);
-      return this;
-    }
-
-    /**
-     * Add a hex-encoded random segment to the path being accumulated.
-     *
-     * @param nBytes The number of random bytes in the segment.
-     * @return The builder, for convenience.
-     */
-    public UriBuilder addRandomSegment(int nBytes) {
-      return addSegment(generateRandomNonceHex(nBytes));
-    }
-
-    /**
-     * @return The URI composed of the accumulated parts.
-     * @throws IllegalArgumentException if there's a syntax problem with one of the parts.
-     */
-    public URI build() {
-      try {
-        return new URI(scheme, host, pathBuilder.toString(), null);
-      } catch (URISyntaxException e) {
-        throw new IllegalArgumentException(e);
-      }
-    }
-  }
-
-  private static UriBuilder gsaUriBuilder() {
-    return uriBuilder()
-        .addSegment("enterprise")
-        .addSegment("gsa")
-        .addSegment(getGsaEntConfigName());
-  }
-
-  public static UriBuilder smUriBuilder() {
-    return gsaUriBuilder()
-        .addSegment("security-manager");
-  }
-
-  // TODO(cph): make this configurable (preferably in sec mgr config).
-  private static final int THREAD_POOL_SIZE = 20;
-  private static final ExecutorService THREAD_POOL
-      = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
-
-  // Batches of work that are themselves parallizable use a 2nd pool to
-  // parallelize batches while the 1st pool is used for work within the batches.
-  private static final ExecutorService THREAD_POOL_2
-      = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
-
-  // Timeout difference between THREAD_POOL_1 and THREAD_POOL_2.
-  // Otherwise there is a race between their layered use.
-  // So when batches are submitted they use THREAD_POOL_2 to manage
-  // batches, and THREAD_POOL is given less time to carry out tasks.
-  private static final long THREAD_POOL_DELAY_MILLIS = 20;
-
-  @VisibleForTesting
-  static int getPrimaryThreadPoolSize() {
-    return THREAD_POOL_SIZE;
-  }
-
-  /**
-   * Runs a bunch of tasks in parallel using the default/primary thread pool.
-   *
-   * @param callables The tasks to be run.
-   * @param timeoutMillis The maximum amount of time allowed for processing all
-   *     the tasks.
-   * @param sessionId A session ID to use for logging.
-   * @return An immutable list of the computed values, in no particular order.
-   *     The number of values is normally the same as the number of tasks, but
-   *     if the timeoutMillis is reached or if one or more of the tasks generates an
-   *     exception, there will be fewer values than tasks.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static <T> List<T> runInParallel(
-      @Nonnull Iterable<Callable<T>> callables,
-      @Nonnegative long timeoutMillis,
-      @Nonnull String sessionId) {
-    long endTimeMillis = DateTimeUtils.currentTimeMillis() + timeoutMillis;
-    return runInParallel(THREAD_POOL, callables, endTimeMillis, sessionId);
-  }
-
-  private static long calcRemainingMillis(long endTimeMillis) {
-    return endTimeMillis - DateTimeUtils.currentTimeMillis();
-  }
-
-  @CheckReturnValue
-  @Nonnull
-  public static <T> List<T> runBatchesInParallel(
-      @Nonnull Iterable<KeyedBatchOfCallables<T>> keyedBatches, @Nonnegative long timeoutMillis,
-      @Nonnull String sessionId, int maxThreadsPerBatch) {
-    long endTimeMillis = DateTimeUtils.currentTimeMillis() + timeoutMillis;
-
-    /* Convert each batch of callables (a list of callables) into a single
-      callable that has the batch of callables parallelized inside of it */
-    List<Callable<List<T>>> callsWithParallization = Lists.newArrayList();
-    for (KeyedBatchOfCallables<T> keyedBatch : keyedBatches) {
-      Callable<List<T>> oneCallableBatch = keyedBatch
-          .toSingleParallelizedCallable(endTimeMillis, sessionId, maxThreadsPerBatch);
-      callsWithParallization.add(oneCallableBatch);
-    }
-
-    List<List<T>> answerLists = runInParallel(THREAD_POOL_2, callsWithParallization,
-        endTimeMillis, sessionId);
-    ImmutableList.Builder<T> builder = ImmutableList.builder();
-    for (List<T> answerList : answerLists) {
-      builder.addAll(answerList);
-    }
-    return builder.build();
-  }
-
-  @Nonnull
-  private static <T> List<T> runInParallel(
-      @Nonnull ExecutorService threadPool,
-      @Nonnull Iterable<Callable<T>> callables,
-      @Nonnegative long endTimeMillis,
-      @Nonnull String sessionId) {
-    Preconditions.checkNotNull(threadPool);
-    Preconditions.checkNotNull(callables);
-    Preconditions.checkArgument(endTimeMillis >= 0);
-    Preconditions.checkNotNull(sessionId);
-
-    List<T> results = Lists.newArrayList();
-    try {
-      List<Future<T>> futures = threadPool.invokeAll(Lists.newArrayList(callables),
-         calcRemainingMillis(endTimeMillis), TimeUnit.MILLISECONDS);
-      for (Future<T> f : futures) {
-        try {
-          if (f.isDone() && !f.isCancelled()) {
-            T singleResult = f.get();
-            if (null != singleResult) {
-              results.add(singleResult);
-            }
-          }
-        } catch (ExecutionException e) {
-          LOGGER.log(Level.WARNING,
-              SecurityManagerUtil.sessionLogMessage(sessionId, "Exception in worker thread: "),
-              e);
-        }
-      }
-
-    } catch (InterruptedException e) {
-      // Reset the interrupt, then fall through to the cleanup code below.
-      Thread.currentThread().interrupt();
-    }
-    return results;
-  }
-
-  // Contains bounded executors per key.
-  private static HashMap<String, ExecutorService> boundedServicers
-      = new HashMap<String, ExecutorService>();
-
-  /** Returns a bounded executor service for a given key, unless
-    one doesn't exist already, in which it's constructed with
-    maxThreadsPerBatch parameter.  Note that if a bounded executor
-    service by a given name already exists then it's provided
-    without checking that it uses the same number of maxThreadsPerBatch. */
-  private static ExecutorService getServiceForKey(String key, int maxThreadsPerBatch) {
-    ExecutorService service;
-    synchronized(boundedServicers) {
-      if (!boundedServicers.containsKey(key)) {
-        boundedServicers.put(key, new BoundedExecutorService(maxThreadsPerBatch,
-            /*fair*/ false, THREAD_POOL));
-      }
-      service = boundedServicers.get(key);
-    }
-    return service;
-  }
-
-  /** Converts a list of Callables into a single Callable that
-    parallizes the original list of work. */
-  public static class KeyedBatchOfCallables<T> {
-    private final String key;
-    private final List<Callable<T>> work;
-
-    public KeyedBatchOfCallables(String key, List<Callable<T>> work) {
-      this.key = key;
-      this.work = ImmutableList.copyOf(work);
-    }
-
-    /** Returns callable that when invoked performs all the work
-      callables provided in constructor in parallel.  A BoundedExecutorService
-      is used to limit the resources that the parallization takes. */
-    private Callable<List<T>> toSingleParallelizedCallable(final long endTimeMillis,
-        final String sessionId, int maxThreadsPerBatch) {
-      final ExecutorService limitedExecutor = getServiceForKey(key, maxThreadsPerBatch);
-      Callable<List<T>> singleCallable = new Callable<List<T>>() {
-        @Override
-        public List<T> call() {
-          return runInParallel(limitedExecutor, work,
-              endTimeMillis - THREAD_POOL_DELAY_MILLIS, sessionId);
-        }
-      };
-      return singleCallable;
-    }
-  }
 }
diff --git a/src/com/google/enterprise/secmgr/common/SessionUtil.java b/src/com/google/enterprise/secmgr/common/SessionUtil.java
deleted file mode 100644
index cb2474e..0000000
--- a/src/com/google/enterprise/secmgr/common/SessionUtil.java
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.common;
-
-import com.google.common.base.Preconditions;
-
-import java.util.regex.Pattern;
-
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * A collection of session utilities.
- */
-public final class SessionUtil {
-  /**
-   * The name of the GSA session ID cookie.
-   */
-  public static final String GSA_SESSION_ID_COOKIE_NAME = "GSA_SESSION_ID";
-
-  /**
-   * A regular expression that matches a valid session ID; basically alphanumeric.
-   */
-  // TODO(cph): might be useful to broaden this pattern to handle base64.
-  private static final Pattern SESSION_ID_REGEXP = Pattern.compile("[0-9A-Za-z]*");
-
-  /**
-   * The smallest acceptable length for a session ID string.
-   */
-  private static final int MIN_ACCEPTABLE_SESSION_ID_LENGTH = 16;
-
-  /**
-   * The largest acceptable length for a session ID string.
-   */
-  private static final int MAX_ACCEPTABLE_SESSION_ID_LENGTH = 100;
-
-  /**
-   * The length of a generated session ID string.
-   */
-  private static final int GENERATED_SESSION_ID_LENGTH = MIN_ACCEPTABLE_SESSION_ID_LENGTH;
-
-  // Don't instantiate.
-  private SessionUtil() {
-    throw new UnsupportedOperationException();
-  }
-
-  /**
-   * Generate a session ID for a new session.
-   */
-  public static String generateId() {
-    return SecurityManagerUtil.generateRandomNonceHex(GENERATED_SESSION_ID_LENGTH / 2);
-  }
-
-  /**
-   * Is the given string a valid session ID?
-   *
-   * @param proposedId The string to test.
-   * @return True only if the string is valid.
-   */
-  public static boolean isValidId(String proposedId) {
-    return proposedId != null
-        && proposedId.length() >= MIN_ACCEPTABLE_SESSION_ID_LENGTH
-        && proposedId.length() <= MAX_ACCEPTABLE_SESSION_ID_LENGTH
-        && SESSION_ID_REGEXP.matcher(proposedId).matches();
-  }
-
-  /**
-   * Get the GSA session ID by examining the cookies in an incoming request.
-   *
-   * @param request The HTTP request to check the cookies of.
-   * @return The GSA session ID, if a valid one is found; otherwise null.
-   */
-  public static String findGsaSessionId(HttpServletRequest request) {
-    Preconditions.checkNotNull(request);
-    CookieStore cookies = GCookie.parseHttpRequestCookies(request, null);
-    for (GCookie c : cookies) {
-      if (GSA_SESSION_ID_COOKIE_NAME.equalsIgnoreCase(c.getName())
-          && isValidId(c.getValue())) {
-        return c.getValue();
-      }
-    }
-    return null;
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/common/XmlUtil.java b/src/com/google/enterprise/secmgr/common/XmlUtil.java
index 399c85d..365f447 100644
--- a/src/com/google/enterprise/secmgr/common/XmlUtil.java
+++ b/src/com/google/enterprise/secmgr/common/XmlUtil.java
@@ -14,34 +14,20 @@
 
 package com.google.enterprise.secmgr.common;
 
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-
-import org.w3c.dom.Attr;
-import org.w3c.dom.Comment;
 import org.w3c.dom.DOMConfiguration;
 import org.w3c.dom.DOMImplementation;
 import org.w3c.dom.Document;
 import org.w3c.dom.DocumentType;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.Text;
 import org.w3c.dom.bootstrap.DOMImplementationRegistry;
 import org.w3c.dom.ls.DOMImplementationLS;
 import org.w3c.dom.ls.LSException;
-import org.w3c.dom.ls.LSInput;
 import org.w3c.dom.ls.LSOutput;
-import org.w3c.dom.ls.LSParser;
 import org.w3c.dom.ls.LSSerializer;
 
 import java.io.IOException;
-import java.io.Reader;
 import java.io.StringWriter;
 import java.io.Writer;
-import java.util.List;
 
-import javax.xml.XMLConstants;
 import javax.xml.namespace.QName;
 
 /**
@@ -157,25 +143,6 @@
   }
 
   /**
-   * Read an XML document from a file.
-   *
-   * @param input The stream to read the document from.
-   * @return The XML document.
-   * @throws IOException if the document can't be parsed.
-   */
-  public Document readXmlDocument(Reader input)
-      throws IOException {
-    LSInput lsInput = domImplLs.createLSInput();
-    lsInput.setCharacterStream(input);
-    LSParser parser = domImplLs.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null);
-    try {
-      return parser.parse(lsInput);
-    } catch (LSException e) {
-      throw new IOException(e);
-    }
-  }
-
-  /**
    * Write an XML document to a writer.
    *
    * @param document The XML document to write.
@@ -246,338 +213,4 @@
     writeXmlDocument(document, output);
     return output.toString();
   }
-
-  /**
-   * Add a namespace declaration to the given element.
-   *
-   * @param element The element to add the declaration to.
-   * @param prefix The namespace prefix to declare.
-   * @param uri The namespace URI to associate with the given prefix.
-   * @return The namespace declaration as an attribute object.
-   */
-  public static Attr addNamespaceDeclaration(Element element, String prefix, String uri) {
-    return makeAttrChild(
-        element,
-        new QName(
-            XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
-            prefix,
-            XMLConstants.XMLNS_ATTRIBUTE),
-        uri);
-  }
-
-  /**
-   * Get the child elements.
-   *
-   * @param parent The parent element to look in.
-   * @return A list of the child elements.
-   */
-  public static List<Element> getChildElements(Element parent) {
-    List<Element> elements = Lists.newArrayList();
-    NodeList nodes = parent.getChildNodes();
-    for (int i = 0; i < nodes.getLength(); i++) {
-      Node node = nodes.item(i);
-      if (node instanceof Element) {
-        elements.add((Element) node);
-      }
-    }
-    return elements;
-  }
-
-  /**
-   * Find a child element with a given name.
-   *
-   * @param parent The parent element to look in.
-   * @param qname The qname of the child element to look for.
-   * @param required True if the method should throw an exception when no such child.
-   * @return The specified child element, or null if non such (and required is false).
-   * @throws IllegalArgumentException if required is true and there's no such child.
-   */
-  public static Element findChildElement(Element parent, QName qname, boolean required) {
-    NodeList nodes = parent.getChildNodes();
-    for (int i = 0; i < nodes.getLength(); i++) {
-      Node node = nodes.item(i);
-      if (isElementWithQname(node, qname)) {
-        return (Element) node;
-      }
-    }
-    if (required) {
-      throw new IllegalArgumentException(
-          "Entity doesn't contain child named " + qname.toString());
-    }
-    return null;
-  }
-
-  /**
-   * Get the child elements with a given name.
-   *
-   * @param parent The parent element to look in.
-   * @param qname The qname of the child elements to retrieve.
-   * @return A list of the child elements with the given tag name.
-   */
-  public static List<Element> getChildElements(Element parent, QName qname) {
-    List<Element> elements = Lists.newArrayList();
-    NodeList nodes = parent.getChildNodes();
-    for (int i = 0; i < nodes.getLength(); i++) {
-      Node node = nodes.item(i);
-      if (isElementWithQname(node, qname)) {
-        elements.add((Element) node);
-      }
-    }
-    return elements;
-  }
-
-  /**
-   * Count the child elements with a given name.
-   *
-   * @param parent The parent element to look in.
-   * @param qname The qname of the child elements to look for.
-   * @return The number of child elements with the given tag name.
-   */
-  public static int countChildElements(Element parent, QName qname) {
-    int nElements = 0;
-    NodeList nodes = parent.getChildNodes();
-    for (int i = 0; i < nodes.getLength(); i++) {
-      Node node = nodes.item(i);
-      if (isElementWithQname(node, qname)) {
-        nElements += 1;
-      }
-    }
-    return nElements;
-  }
-
-  public static boolean isElementWithQname(Node node, QName qname) {
-    return node instanceof Element && elementHasQname((Element) node, qname);
-  }
-
-  /**
-   * Compare an element's tag name to a given name.
-   *
-   * @param element The element to get the tag name from.
-   * @param qname The qname to compare to.
-   * @return True if the element's tag name and namespace URI match those of the qname.
-   */
-  public static boolean elementHasQname(Element element, QName qname) {
-    return qname.getLocalPart().equals(element.getLocalName())
-        && qname.getNamespaceURI().equals(getNamespaceUri(element));
-  }
-
-  /**
-   * Get the namespace URI of a given element.
-   *
-   * @param element The element to get the namespace URI of.
-   * @return The namespace URI, or the null namespace URI if the element has none.
-   */
-  public static String getNamespaceUri(Element element) {
-    String namespace = element.getNamespaceURI();
-    return (namespace != null) ? namespace : XMLConstants.NULL_NS_URI;
-  }
-
-  /**
-   * Get the text from an element that contains only text.
-   *
-   * @param element The element to get the text from.
-   * @return The text contained in that element.
-   * @throws IllegalArgumentException if the element isn't text-only.
-   */
-  public static String getElementText(Element element) {
-    NodeList nodes = element.getChildNodes();
-    Preconditions.checkArgument(nodes.getLength() == 1
-        && nodes.item(0).getNodeType() == Node.TEXT_NODE);
-    return nodes.item(0).getNodeValue();
-  }
-
-  /**
-   * Get the text from a child element that contains only text.
-   *
-   * @param parent The parent element to look in.
-   * @param qname The qname of the child element to look for.
-   * @param required True if the method should throw an exception when no such child.
-   * @return The text of the specified child element, or null if non such (and required is false).
-   * @throws IllegalArgumentException if required is true and there's no such child.
-   */
-  public static String getChildElementText(Element parent, QName qname, boolean required) {
-    Element child = findChildElement(parent, qname, required);
-    return (child != null) ? getElementText(child) : null;
-  }
-
-  /**
-   * Find all the comments in a given element that contain some given text.
-   *
-   * @param parent The parent element to look in.
-   * @param text The comment string to search for.
-   * @return A list of the comments containing that string.
-   */
-  public static List<Comment> findChildComments(Element parent, String text) {
-    List<Comment> comments = Lists.newArrayList();
-    NodeList nodes = parent.getChildNodes();
-    for (int index = 0; index < nodes.getLength(); index++) {
-      Node node = nodes.item(index);
-      if (node instanceof Comment && node.getNodeValue().contains(text)) {
-        comments.add((Comment) node);
-      }
-    }
-    return comments;
-  }
-
-  /**
-   * Get the descendant elements with a given name.
-   *
-   * @param parent The parent element to look in.
-   * @param qname The qname of the descendant elements to look for.
-   * @return A list of the descendant elements with the given tag name.
-   */
-  public static NodeList getElementsByQname(Element parent, QName qname) {
-    return parent.getElementsByTagNameNS(qname.getNamespaceURI(), qname.getLocalPart());
-  }
-
-  /**
-   * Get a given element's attribute with a given name.
-   *
-   * @param element The element to get the attribute from.
-   * @param qname The qname of the attribute to look for.
-   * @param required True if the method should throw an exception when no such attribute.
-   * @return The attribute's value, or null if no such attribute (and required is false).
-   * @throws IllegalArgumentException if no such attribute and required is true.
-   */
-  public static String findAttribute(Element element, QName qname, boolean required) {
-    String ns = qname.getNamespaceURI();
-    String localName = qname.getLocalPart();
-    if (ns.isEmpty()) {
-      ns = null;
-    }
-    if (element.hasAttributeNS(ns, localName)) {
-      String value = element.getAttributeNS(ns, localName);
-      return value;
-    }
-    if (required) {
-      throw new IllegalArgumentException(
-          "Entity doesn't contain attribute named " + qname.toString());
-    }
-    return null;
-  }
-
-  /**
-   * Make a new DOM element child.
-   *
-   * @param parent The element to put the new child element in.
-   * @param qname The qname of the new child element.
-   * @return The new child element.
-   */
-  public static Element makeElementChild(Element parent, QName qname) {
-    Element child = makeElement(parent, qname);
-    parent.appendChild(child);
-    return child;
-  }
-
-  /**
-   * Make a new DOM text child.
-   *
-   * @param parent The element to put the new child text in.
-   * @param content The text content of the new child.
-   * @return The new child text.
-   */
-  public static Text makeTextChild(Element parent, String content) {
-    Text child = makeText(parent, content);
-    parent.appendChild(child);
-    return child;
-  }
-
-  /**
-   * Make a new DOM element child containing some text.
-   *
-   * @param parent The element to put the new child element in.
-   * @param qname The name of the new child element.
-   * @param content The text content of the new child element.
-   * @return The new child element.
-   */
-  public static Element makeTextElementChild(Element parent, QName qname, String content) {
-    Element child = makeElementChild(parent, qname);
-    makeTextChild(child, content);
-    return child;
-  }
-
-  /**
-   * Make a new DOM comment child.
-   *
-   * @param parent The element to put the new child comment in.
-   * @param content The text content of the new child comment.
-   * @return The new child comment.
-   */
-  public static Comment makeCommentChild(Element parent, String content) {
-    Comment child = makeComment(parent, content);
-    parent.appendChild(child);
-    return child;
-  }
-
-  /**
-   * Make a new DOM attribute child.
-   *
-   * @param parent The element to put the new child attribute in.
-   * @param qname The qname of the new child attribute.
-   * @param value The value of the new child attribute.
-   * @return The new child attribute.
-   */
-  public static Attr makeAttrChild(Element parent, QName qname, String value) {
-    Attr child = makeAttr(parent, qname, value);
-    parent.setAttributeNodeNS(child);
-    return (child);
-  }
-
-  /**
-   * Make a new DOM element.
-   *
-   * @param element Any element in the target document for the new element.
-   * @param qname The qname of the new element.
-   * @return The new element.
-   */
-  public static Element makeElement(Element element, QName qname) {
-    return element.getOwnerDocument()
-        .createElementNS(qname.getNamespaceURI(), qnameToString(qname));
-  }
-
-  /**
-   * Make a new DOM text.
-   *
-   * @param element Any element in the target document for the new text.
-   * @param content The content of the new text.
-   * @return The new text.
-   */
-  public static Text makeText(Element element, String content) {
-    return element.getOwnerDocument().createTextNode(content);
-  }
-
-  /**
-   * Make a new DOM comment.
-   *
-   * @param element Any element in the target document for the new comment.
-   * @param content The content of the new comment.
-   * @return The new comment.
-   */
-  public static Comment makeComment(Element element, String content) {
-    return element.getOwnerDocument().createComment(content);
-  }
-
-  /**
-   * Make a new DOM attribute.
-   *
-   * @param element Any element in the target document for the new attribute.
-   * @param qname The qname of the new attribute.
-   * @param value The attribute's value.
-   * @return The new attribute.
-   */
-  public static Attr makeAttr(Element element, QName qname, String value) {
-    Attr attr = element.getOwnerDocument()
-        .createAttributeNS(qname.getNamespaceURI(), qnameToString(qname));
-    attr.setValue(value);
-    return attr;
-  }
-
-  private static String qnameToString(QName qname) {
-    String localPart = qname.getLocalPart();
-    String prefix = qname.getPrefix();
-    return
-        (XMLConstants.DEFAULT_NS_PREFIX.equals(prefix))
-        ? localPart
-        : prefix + ":" + localPart;
-  }
 }
diff --git a/src/com/google/enterprise/secmgr/config/AuthnAuthority.java b/src/com/google/enterprise/secmgr/config/AuthnAuthority.java
deleted file mode 100644
index 64599aa..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnAuthority.java
+++ /dev/null
@@ -1,224 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Maps;
-import com.google.enterprise.secmgr.common.SecurityManagerUtil;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-
-import java.lang.reflect.Type;
-import java.net.URI;
-import java.util.Map;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.GuardedBy;
-import javax.annotation.concurrent.ThreadSafe;
-
-/**
- * An authentication authority describes an authority that validates credentials.
- */
-@ThreadSafe
-@ParametersAreNonnullByDefault
-public class AuthnAuthority {
-  @GuardedBy("itself")
-  @Nonnull static final Map<URI, AuthnAuthority> AUTHORITIES = Maps.newHashMap();
-
-  @Nonnull private final URI uri;
-
-  private AuthnAuthority(URI uri) {
-    this.uri = uri;
-  }
-
-  /**
-   * Makes an authority.
-   *
-   * @param uri The URI for this authority.
-   * @return The unique authority with that URI, creating it if necessary.
-   * @throws IllegalArgumentException if the URI is invalid.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static AuthnAuthority make(URI uri) {
-    checkUri(uri);
-    AuthnAuthority authority;
-    synchronized (AUTHORITIES) {
-      authority = AUTHORITIES.get(uri);
-      if (authority == null) {
-        authority = new AuthnAuthority(uri);
-        AUTHORITIES.put(uri, authority);
-      }
-    }
-    return authority;
-  }
-
-  private static void checkUri(URI uri) {
-    Preconditions.checkNotNull(uri);
-    Preconditions.checkArgument(uri.isAbsolute());
-    Preconditions.checkArgument(!uri.isOpaque());
-    Preconditions.checkArgument(uri.getQuery() == null);
-    Preconditions.checkArgument(uri.getFragment() == null);
-  }
-
-  static AuthnAuthority make(String configName) {
-    return make(SecurityManagerUtil.smUriBuilder().addSegment(configName).build());
-  }
-
-  @VisibleForTesting
-  public static AuthnAuthority make() {
-    return make(SecurityManagerUtil.smUriBuilder().addRandomSegment(16).build());
-  }
-
-  /**
-   * Gets a globally-unique URI for this authority.
-   *
-   * @return The authority's URI.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public URI getUri() {
-    return uri;
-  }
-
-  /**
-   * Gets a globally-unique name for this authority.  Equivalent to
-   * {@code getUri().toString()}.
-   *
-   * @return The authority's name.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public String getName() {
-    return uri.toString();
-  }
-
-  /**
-   * Gets an authority given its URI.
-   *
-   * @param uri The URI of the authority to find.
-   * @return The corresponding authority, or {@code null} if no authority has that URI.
-   */
-  @CheckReturnValue
-  @Nullable
-  public static AuthnAuthority lookupByUri(URI uri) {
-    checkUri(uri);
-    synchronized (AUTHORITIES) {
-      return AUTHORITIES.get(uri);
-    }
-  }
-
-  /**
-   * Gets an authority given its name.
-   *
-   * @param name The name of the authority to find.
-   * @return The corresponding authority, or {@code null} if no authority has that name.
-   */
-  @CheckReturnValue
-  @Nullable
-  public static AuthnAuthority lookupByName(String name) {
-    return lookupByUri(URI.create(name));
-  }
-
-  /**
-   * Gets an authority given its name.
-   *
-   * @param name The name of the authority to find.
-   * @return The corresponding authority.
-   * @throw IllegalArgumentException if no such authority.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static AuthnAuthority getByName(String name) {
-    AuthnAuthority authority = lookupByName(name);
-    if (authority == null) {
-      throw new IllegalArgumentException("No authority of this name: " + name);
-    }
-    return authority;
-  }
-
-  @VisibleForTesting
-  public static void clearAuthorities() {
-    synchronized (AUTHORITIES) {
-      AUTHORITIES.clear();
-    }
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof AuthnAuthority)) { return false; }
-    AuthnAuthority other = (AuthnAuthority) object;
-    return getUri().equals(other.getUri());
-  }
-
-  @Override
-  public int hashCode() {
-    return getUri().hashCode();
-  }
-
-  @Override
-  public String toString() {
-    return getName();
-  }
-
-  /**
-   * Gets a predicate that is true for an authority with a given URI.
-   *
-   * @param uri The authority URI to test for.
-   * @return The predicate corresponding to the name.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Predicate<AuthnAuthority> getUriPredicate(final URI uri) {
-    return new Predicate<AuthnAuthority>() {
-      public boolean apply(AuthnAuthority authority) {
-        return uri.equals(authority.getUri());
-      }
-    };
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(AuthnAuthority.class, new LocalTypeAdapter());
-  }
-
-  private static final class LocalTypeAdapter
-      implements JsonSerializer<AuthnAuthority>, JsonDeserializer<AuthnAuthority> {
-    LocalTypeAdapter() {
-    }
-
-    @Override
-    public JsonElement serialize(AuthnAuthority value, Type type,
-        JsonSerializationContext context) {
-      return context.serialize(value.getName(), String.class);
-    }
-
-    @Override
-    public AuthnAuthority deserialize(JsonElement elt, Type type,
-        JsonDeserializationContext context) {
-      String string = context.deserialize(elt, String.class);
-      return make(URI.create(string));
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechBasic.java b/src/com/google/enterprise/secmgr/config/AuthnMechBasic.java
deleted file mode 100644
index 462b8cb..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechBasic.java
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The configuration of an HTTP Basic authentication mechanism.
- */
-@Immutable
-public final class AuthnMechBasic extends AuthnMechanism {
-
-  public static final String TYPE_NAME = "Basic";
-  private static final long DEFAULT_TRUST_DURATION = 20 * 60 * 1000;  // 20 mins
-
-  private final String sampleUrl;
-  private final long trustDuration;
-
-  /**
-   * Make a new HTTP Basic mechanism.
-   *
-   * @param sampleUrl A sample URL that requires HTTP Basic authentication.
-   * @param trustDuration The number of milliseconds for which successfully
-   *     verified credentials are trusted.  This must be a non-negative number.
-   * @return A new mechanism with the given elements.
-   */
-  public static AuthnMechBasic make(String name, String sampleUrl, long trustDuration) {
-    return new AuthnMechBasic(name, sampleUrl, trustDuration);
-  }
-
-  /**
-   * Make a new HTTP Basic mechanism with a default trust duration.
-   *
-   * @param sampleUrl A sample URL that requires HTTP Basic authentication.
-   * @return A new mechanism with the given elements.
-   */
-  public static AuthnMechBasic make(String name, String sampleUrl) {
-    return make(name, sampleUrl, getDefaultTrustDuration());
-  }
-
-  private AuthnMechBasic(String name, String sampleUrl, long trustDuration) {
-    super(name);
-    this.sampleUrl = checkString(sampleUrl);
-    this.trustDuration = checkTrustDuration(trustDuration);
-  }
-
-  /**
-   * Make a new unconfigured HTTP Basic mechanism.
-   */
-  public static AuthnMechBasic makeEmpty() {
-    return new AuthnMechBasic();
-  }
-
-  private AuthnMechBasic() {
-    super();
-    this.sampleUrl = null;
-    this.trustDuration = getDefaultTrustDuration();
-  }
-
-  @Override
-  public String getTypeName() {
-    return TYPE_NAME;
-  }
-
-  /**
-   * Get the default trust-duration value.
-   */
-  public static long getDefaultTrustDuration() {
-    return DEFAULT_TRUST_DURATION;
-  }
-
-  @Override
-  public List<CredentialTransform> getCredentialTransforms() {
-    return ImmutableList.of(
-        CredentialTransform.make(
-            CredentialTypeSet.PRINCIPAL_AND_PASSWORD,
-            CredentialTypeSet.VERIFIED_PRINCIPAL_AND_PASSWORD));
-  }
-
-  @Override
-  public AuthnMechanism copyWithNewName(String name) {
-    return make(name, getSampleUrl(), getTrustDuration());
-  }
-
-  @Override
-  public String getSampleUrl() {
-    return sampleUrl;
-  }
-
-  @Override
-  public long getTrustDuration() {
-    return trustDuration;
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof AuthnMechBasic)) { return false; }
-    AuthnMechBasic mech = (AuthnMechBasic) object;
-    return super.equals(mech)
-        && Objects.equal(getSampleUrl(), mech.getSampleUrl())
-        && Objects.equal(getTrustDuration(), mech.getTrustDuration());
-  }
-
-  @Override
-  public int hashCode() {
-    return super.hashCode(getSampleUrl(), getTrustDuration());
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(AuthnMechBasic.class,
-        ProxyTypeAdapter.make(AuthnMechBasic.class, LocalProxy.class));
-  }
-
-  private static final class LocalProxy extends MechanismProxy<AuthnMechBasic> {
-    String sampleUrl;
-    long trustDuration = DEFAULT_TRUST_DURATION;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(AuthnMechBasic mechanism) {
-      super(mechanism);
-      sampleUrl = mechanism.getSampleUrl();
-      trustDuration = mechanism.getTrustDuration();
-    }
-
-    @Override
-    public AuthnMechBasic build() {
-      return make(name, sampleUrl, trustDuration);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechClient.java b/src/com/google/enterprise/secmgr/config/AuthnMechClient.java
deleted file mode 100644
index 3dd7c29..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechClient.java
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The configuration of a client certificate authentication mechanism.
- */
-@Immutable
-public final class AuthnMechClient extends AuthnMechanism {
-
-  public static final String TYPE_NAME = "X509Client";
-  private static final long DEFAULT_TRUST_DURATION = 20 * 60 * 1000;  // 20 mins
-
-  /**
-   * Make a new ClientAuth mechanism.
-   */
-  public static AuthnMechClient make(String name) {
-    return new AuthnMechClient(name);
-  }
-
-  private AuthnMechClient(String name) {
-    super(name);
-  }
-
-  /**
-   * Make a new unconfigured ClientAuth mechanism.
-   */
-  public static AuthnMechClient makeEmpty() {
-    return new AuthnMechClient();
-  }
-
-  private AuthnMechClient() {
-    super();
-  }
-
-  @Override
-  public String getTypeName() {
-    return TYPE_NAME;
-  }
-
-  /**
-   * Get the default trust-duration value.
-   */
-  public static long getDefaultTrustDuration() {
-    return DEFAULT_TRUST_DURATION;
-  }
-
-  @Override
-  public List<CredentialTransform> getCredentialTransforms() {
-    return ImmutableList.of(
-        CredentialTransform.make(CredentialTypeSet.NONE, CredentialTypeSet.VERIFIED_PRINCIPAL));
-  }
-
-  @Override
-  public AuthnMechanism copyWithNewName(String name) {
-    return make(name);
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    return (object instanceof AuthnMechClient);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hashCode(TYPE_NAME);
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(AuthnMechClient.class,
-        ProxyTypeAdapter.make(AuthnMechClient.class, LocalProxy.class));
-  }
-
-  private static final class LocalProxy extends MechanismProxy<AuthnMechClient> {
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(AuthnMechClient mechanism) {
-      super(mechanism);
-    }
-
-    @Override
-    public AuthnMechClient build() {
-      return make(name);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechConnector.java b/src/com/google/enterprise/secmgr/config/AuthnMechConnector.java
deleted file mode 100644
index eb87fe2..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechConnector.java
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The configuration of a connector authentication mechanism.
- */
-@Immutable
-public final class AuthnMechConnector extends AuthnMechanism {
-
-  public static final String TYPE_NAME = "Connector";
-  private static final long DEFAULT_TRUST_DURATION = 20 * 60 * 1000;  // 20 mins
-
-  private final String connectorName;
-  private final boolean doGroupLookupOnly;
-  private final long trustDuration;
-
-  /**
-   * Makes a new connector mechanism.
-   *
-   * @param name The name for the new mechanism.
-   * @param connectorName The name of the connector to use.
-   * @param doGroupLookupOnly To do only groups lookup and not authentication.
-   * @param trustDuration The number of milliseconds for which successfully
-   *     verified credentials are trusted.  This must be a non-negative number.
-   * @return A new mechanism with the given elements.
-   */
-  public static AuthnMechConnector make(String name, String connectorName,
-      boolean doGroupLookupOnly, long trustDuration) {
-    return new AuthnMechConnector(name, connectorName, doGroupLookupOnly, trustDuration);
-  }
-
-  /**
-   * Makes a new connector mechanism with a default trust duration.
-   *
-   * @param name The name for the new mechanism.
-   * @param connectorName The name of the connector to use.
-   * @param doGroupLookupOnly To do only groups lookup and not authentication.
-   * @return A new mechanism with the given elements.
-   */
-  public static AuthnMechConnector make(String name, String connectorName,
-      boolean doGroupLookupOnly) {
-    return make(name, connectorName, doGroupLookupOnly, getDefaultTrustDuration());
-  }
-
-  private AuthnMechConnector(String name, String connectorName, boolean doGroupLookupOnly,
-      long trustDuration) {
-    super(name);
-    this.connectorName = checkString(connectorName);
-    this.doGroupLookupOnly = doGroupLookupOnly;
-    this.trustDuration = checkTrustDuration(trustDuration);
-  }
-
-  /**
-   * Makes a new unconfigured connector mechanism.
-   */
-  public static AuthnMechConnector makeEmpty() {
-    return new AuthnMechConnector();
-  }
-
-  private AuthnMechConnector() {
-    super();
-    this.connectorName = null;
-    this.doGroupLookupOnly = false;
-    this.trustDuration = getDefaultTrustDuration();
-  }
-
-  @Override
-  public String getTypeName() {
-    return TYPE_NAME;
-  }
-
-  /**
-   * Does this connector implement group lookup but not verification?
-   *
-   * @return True only if so.
-   */
-  public boolean doGroupLookupOnly() {
-    return doGroupLookupOnly;
-  }
-
-  /**
-   * Gets the default trust-duration value.
-   */
-  public static long getDefaultTrustDuration() {
-    return DEFAULT_TRUST_DURATION;
-  }
-
-  @Override
-  public List<CredentialTransform> getCredentialTransforms() {
-    return ImmutableList.of(
-        doGroupLookupOnly()
-        ? CredentialTransform.make(
-            CredentialTypeSet.VERIFIED_PRINCIPAL,
-            CredentialTypeSet.VERIFIED_GROUPS)
-        : CredentialTransform.make(
-            CredentialTypeSet.PRINCIPAL_AND_PASSWORD,
-            CredentialTypeSet.VERIFIED_PRINCIPAL_PASSWORD_AND_GROUPS));
-  }
-
-  @Override
-  public AuthnMechanism copyWithNewName(String name) {
-    return make(name, getConnectorName(), doGroupLookupOnly(), getTrustDuration());
-  }
-
-  @Override
-  public long getTrustDuration() {
-    return trustDuration;
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof AuthnMechConnector)) { return false; }
-    AuthnMechConnector mech = (AuthnMechConnector) object;
-    return super.equals(mech)
-        && Objects.equal(getConnectorName(), mech.getConnectorName())
-        && Objects.equal(getTrustDuration(), mech.getTrustDuration());
-  }
-
-  @Override
-  public int hashCode() {
-    return super.hashCode(getConnectorName(), getTrustDuration());
-  }
-
-  /**
-   * Gets the name of this connector.
-   *
-   * @return The connector name, never null or empty.
-   */
-  public String getConnectorName() {
-    return connectorName;
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(AuthnMechConnector.class,
-        ProxyTypeAdapter.make(AuthnMechConnector.class, LocalProxy.class));
-  }
-
-  private static final class LocalProxy extends MechanismProxy<AuthnMechConnector> {
-    String connectorName;
-    boolean doGroupLookupOnly;
-    long trustDuration = DEFAULT_TRUST_DURATION;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(AuthnMechConnector mechanism) {
-      super(mechanism);
-      connectorName = mechanism.getConnectorName();
-      doGroupLookupOnly = mechanism.doGroupLookupOnly();
-      trustDuration = mechanism.getTrustDuration();
-    }
-
-    @Override
-    public AuthnMechConnector build() {
-      return make(name, connectorName, doGroupLookupOnly, trustDuration);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechForm.java b/src/com/google/enterprise/secmgr/config/AuthnMechForm.java
deleted file mode 100644
index 7244b94..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechForm.java
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The configuration of a form SSO authentication mechanism.
- */
-@Immutable
-public final class AuthnMechForm extends AuthnMechanism {
-
-  public static final String TYPE_NAME = "CookieBased";
-  private static final long DEFAULT_TRUST_DURATION = 5 * 60 * 1000;  // 5 minutes
-
-  private final String sampleUrl;
-  private final long trustDuration;
-
-  private AuthnMechForm(String name, String sampleUrl, long trustDuration) {
-    super(name);
-    this.sampleUrl = checkStringOrNull(sampleUrl);
-    this.trustDuration = checkTrustDuration(trustDuration);
-  }
-
-  /**
-   * Makes a new HTTP form mechanism.
-   *
-   * @param name A name for the new mechanism.
-   * @param sampleUrl A sample URL that is protected by form authentication.
-   * @param trustDuration The number of milliseconds that successfully
-   *     verified credentials are trusted.  This must be a non-negative number.
-   * @return A new mechanism with the given elements.
-   */
-  public static AuthnMechForm make(String name, String sampleUrl, long trustDuration) {
-    return new AuthnMechForm(name, sampleUrl, trustDuration);
-  }
-
-  /**
-   * Makes a new HTTP form mechanism with a default trust duration.
-   *
-   * @param name A name for the new mechanism.
-   * @param sampleUrl A sample URL that is protected by form authentication.
-   * @return A new mechanism with the given elements.
-   */
-  public static AuthnMechForm make(String name, String sampleUrl) {
-    return make(name, sampleUrl, getDefaultTrustDuration());
-  }
-
-  /**
-   * Make a new unconfigured HTTP form mechanism.
-   */
-  public static AuthnMechForm makeEmpty() {
-    return new AuthnMechForm();
-  }
-
-  private AuthnMechForm() {
-    super();
-    this.sampleUrl = null;
-    this.trustDuration = getDefaultTrustDuration();
-  }
-
-  @Override
-  public String getTypeName() {
-    return TYPE_NAME;
-  }
-
-  /**
-   * Get the default trust-duration value.
-   */
-  public static long getDefaultTrustDuration() {
-    return DEFAULT_TRUST_DURATION;
-  }
-
-  @Override
-  public List<CredentialTransform> getCredentialTransforms() {
-    return ImmutableList.of(
-        CredentialTransform.make(
-            CredentialTypeSet.PRINCIPAL_AND_PASSWORD,
-            CredentialTypeSet.VERIFIED_PRINCIPAL_AND_PASSWORD),
-        CredentialTransform.make(CredentialTypeSet.COOKIES, CredentialTypeSet.VERIFIED_PRINCIPAL),
-        CredentialTransform.make(CredentialTypeSet.COOKIES, CredentialTypeSet.VERIFIED_ALIASES),
-        CredentialTransform.make(CredentialTypeSet.COOKIES, CredentialTypeSet.VERIFIED_GROUPS));
-  }
-
-  @Override
-  public AuthnMechanism copyWithNewName(String name) {
-    return make(name, getSampleUrl(), getTrustDuration());
-  }
-
-  @Override
-  public String getSampleUrl() {
-    return sampleUrl;
-  }
-
-  @Override
-  public long getTrustDuration() {
-    return trustDuration;
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof AuthnMechForm)) { return false; }
-    AuthnMechForm mech = (AuthnMechForm) object;
-    return super.equals(mech)
-        && Objects.equal(getSampleUrl(), mech.getSampleUrl())
-        && Objects.equal(getTrustDuration(), mech.getTrustDuration());
-  }
-
-  @Override
-  public int hashCode() {
-    return super.hashCode(getSampleUrl(), getTrustDuration());
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(AuthnMechForm.class,
-        ProxyTypeAdapter.make(AuthnMechForm.class, LocalProxy.class));
-  }
-
-  private static final class LocalProxy extends MechanismProxy<AuthnMechForm> {
-    String sampleUrl;
-    long trustDuration = DEFAULT_TRUST_DURATION;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(AuthnMechForm mechanism) {
-      super(mechanism);
-      sampleUrl = mechanism.getSampleUrl();
-      trustDuration = mechanism.getTrustDuration();
-    }
-
-    @Override
-    public AuthnMechForm build() {
-      return make(name, sampleUrl, trustDuration);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechKerberos.java b/src/com/google/enterprise/secmgr/config/AuthnMechKerberos.java
deleted file mode 100644
index 16e7f0f..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechKerberos.java
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The configuration of a kerberos authentication mechanism.
- */
-@Immutable
-public final class AuthnMechKerberos extends AuthnMechanism {
-
-  public static final String TYPE_NAME = "Kerberos";
-  private static final long DEFAULT_TRUST_DURATION = 5 * 60 * 1000;  // 5 minutes
-
-  /**
-   * Make a new Kerberos mechanism.
-   */
-  public static AuthnMechKerberos make(String name) {
-    return new AuthnMechKerberos(name);
-  }
-
-  private AuthnMechKerberos(String name) {
-    super(name);
-  }
-
-  /**
-   * Make a new unconfigured Kerberos mechanism.
-   */
-  public static AuthnMechKerberos makeEmpty() {
-    return new AuthnMechKerberos();
-  }
-
-  private AuthnMechKerberos() {
-    super();
-  }
-
-  @Override
-  public String getTypeName() {
-    return TYPE_NAME;
-  }
-
-  /**
-   * TODO(jiajia): do we need to place the kerb ticket expiration time here?
-   */
-  @Override
-  public long getTrustDuration() {
-    return getDefaultTrustDuration();
-  }
-
-  /**
-   * Get the default trust-duration value.
-   */
-  public static long getDefaultTrustDuration() {
-    return DEFAULT_TRUST_DURATION;
-  }
-
-  @Override
-  public List<CredentialTransform> getCredentialTransforms() {
-    return ImmutableList.of(
-        CredentialTransform.make(CredentialTypeSet.NONE, CredentialTypeSet.VERIFIED_PRINCIPAL));
-  }
-
-  @Override
-  public AuthnMechanism copyWithNewName(String name) {
-    return make(name);
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    return (object instanceof AuthnMechKerberos);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hashCode(TYPE_NAME);
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(AuthnMechKerberos.class,
-        ProxyTypeAdapter.make(AuthnMechKerberos.class, LocalProxy.class));
-  }
-
-  private static final class LocalProxy extends MechanismProxy<AuthnMechKerberos> {
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(AuthnMechKerberos mechanism) {
-      super(mechanism);
-    }
-
-    @Override
-    public AuthnMechKerberos build() {
-      return make(name);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechLdap.java b/src/com/google/enterprise/secmgr/config/AuthnMechLdap.java
deleted file mode 100644
index 3b2a781..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechLdap.java
+++ /dev/null
@@ -1,261 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-/**
- * LDAP configuration.
- */
-public final class AuthnMechLdap extends AuthnMechanism {
-
-  public static final String TYPE_NAME = "LDAP";
-  private static final long DEFAULT_TRUST_DURATION = 20 * 60 * 1000;  // 20 mins
-
-  private final boolean enableAuthn;
-  private final boolean enableGroupLookup;
-
-  private final String hostport;
-  private final String bindDn;
-  private final String password;
-  private final String searchBase;
-  private final String userSearchFilter;
-  private final String groupSearchFilter;
-  private final int sslSupport;
-  private final int supportedAuthMethods;
-
-  private final long trustDuration;
-
-  /**
-   * Make a new LDAP AuthN mechanism.
-   *
-   * @param hostport a hostname and port of the format "HOST:PORT"
-   * @param bindDn the DN to bind with, or empty for anonymous binding
-   * @param password the password to bind with, or empty for anonymous binding
-   * @param searchBase component of DN common to all users
-   * @param userSearchFilter filter used to search for user
-   * @param groupSearchFilter filter used to find user's groups
-   * @param sslSupport the type of SSL to use
-   * @param supportedAuthMethods the auth methods supported by the server
-   * @param enableAuthn whether this mech is enabled for authentication
-   * @param enableGroupLookup whether this mech is enabled for doing groups lookup
-   * @param trustDuration The number of milliseconds for which successfully
-   *     verified credentials are trusted.  This must be a non-negative number.
-   * @return A new mechanism with the given configuration
-   */
-  public static AuthnMechLdap make(String name, String hostport, String bindDn,
-                                   String password, String searchBase,
-                                   String userSearchFilter, String groupSearchFilter,
-                                   int sslSupport, int supportedAuthMethods,
-                                   boolean enableAuthn, boolean enableGroupLookup,
-                                   long trustDuration) {
-    return new AuthnMechLdap(name, hostport, bindDn, password, searchBase,
-                             userSearchFilter, groupSearchFilter, sslSupport,
-                             supportedAuthMethods, enableAuthn, enableGroupLookup,
-                             trustDuration);
-  }
-
-  private AuthnMechLdap(String name, String hostport, String bindDn, String password,
-                        String searchBase, String userSearchFilter, String groupSearchFilter,
-                        int sslSupport, int supportedAuthMethods, boolean enableAuthn,
-                        boolean enableGroupLookup, long trustDuration) {
-    super(name);
-    this.hostport = hostport;
-    this.bindDn = bindDn;
-    this.password = password;
-    this.searchBase = searchBase;
-    this.userSearchFilter = userSearchFilter;
-    this.groupSearchFilter = groupSearchFilter;
-    this.sslSupport = sslSupport;
-    this.supportedAuthMethods = supportedAuthMethods;
-    this.enableAuthn = enableAuthn;
-    this.enableGroupLookup = enableGroupLookup;
-    this.trustDuration = trustDuration;
-  }
-
-  public static AuthnMechLdap makeEmpty() {
-    return new AuthnMechLdap();
-  }
-
-  private AuthnMechLdap() {
-    super();
-    this.hostport = null;
-    this.bindDn = null;
-    this.password = null;
-    this.searchBase = null;
-    this.userSearchFilter = null;
-    this.groupSearchFilter = null;
-    this.sslSupport = 0;
-    this.supportedAuthMethods = 0;
-    this.enableAuthn = false;
-    this.enableGroupLookup = false;
-    this.trustDuration = getDefaultTrustDuration();
-  }
-
-  public String getHostport() {
-    return hostport;
-  }
-
-  public String getBindDn() {
-    return bindDn;
-  }
-
-  public String getPassword() {
-    return password;
-  }
-
-  public String getSearchBase() {
-    return searchBase;
-  }
-
-  public String getUserSearchFilter() {
-    return userSearchFilter;
-  }
-
-  public String getGroupSearchFilter() {
-    return groupSearchFilter;
-  }
-
-  public int getSslSupport() {
-    return sslSupport;
-  }
-
-  public int getSupportedAuthMethods() {
-    return supportedAuthMethods;
-  }
-
-  public boolean isEnableAuthn() {
-    return enableAuthn;
-  }
-
-  public boolean isEnableGroupLookup() {
-    return enableGroupLookup;
-  }
-
-  @Override
-  public long getTrustDuration() {
-    return trustDuration;
-  }
-
-  @Override
-  public String getTypeName() {
-    return TYPE_NAME;
-  }
-
-  @Override
-  public List<CredentialTransform> getCredentialTransforms() {
-    ImmutableList.Builder<CredentialTransform> builder = ImmutableList.builder();
-    if (isEnableAuthn()) {
-      builder.add(
-          CredentialTransform.make(
-              CredentialTypeSet.PRINCIPAL_AND_PASSWORD,
-              CredentialTypeSet.VERIFIED_PRINCIPAL_AND_PASSWORD));
-    }
-    if (isEnableGroupLookup()) {
-      builder.add(
-          CredentialTransform.make(
-              CredentialTypeSet.VERIFIED_PRINCIPAL,
-              CredentialTypeSet.VERIFIED_GROUPS));
-    }
-    return builder.build();
-  }
-
-  @Override
-  public AuthnMechanism copyWithNewName(String name) {
-    return make(name, getHostport(), getBindDn(), getPassword(), getSearchBase(),
-        getUserSearchFilter(), getGroupSearchFilter(), getSslSupport(), getSupportedAuthMethods(),
-        isEnableAuthn(), isEnableGroupLookup(), getTrustDuration());
-  }
-
-  public static long getDefaultTrustDuration() {
-    return DEFAULT_TRUST_DURATION;
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof AuthnMechLdap)) { return false; }
-    AuthnMechLdap mech = (AuthnMechLdap) object;
-    return super.equals(mech)
-        && Objects.equal(getHostport(), mech.getHostport())
-        && Objects.equal(getBindDn(), mech.getBindDn())
-        && Objects.equal(getPassword(), mech.getPassword())
-        && Objects.equal(getSearchBase(), mech.getSearchBase())
-        && Objects.equal(getUserSearchFilter(), mech.getUserSearchFilter())
-        && Objects.equal(getGroupSearchFilter(), mech.getGroupSearchFilter())
-        && Objects.equal(getSslSupport(), mech.getSslSupport())
-        && Objects.equal(getSupportedAuthMethods(), mech.getSupportedAuthMethods())
-        && Objects.equal(isEnableAuthn(), mech.isEnableAuthn())
-        && Objects.equal(isEnableGroupLookup(), mech.isEnableGroupLookup()
-        && Objects.equal(getTrustDuration(), mech.getTrustDuration()));
-  }
-
-  @Override
-  public int hashCode() {
-    return super.hashCode(getHostport(), getBindDn(), getPassword(), getSearchBase(),
-        getUserSearchFilter(), getGroupSearchFilter(), getSslSupport(), getSupportedAuthMethods(),
-        isEnableAuthn(), isEnableGroupLookup(), getTrustDuration());
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(AuthnMechLdap.class,
-        ProxyTypeAdapter.make(AuthnMechLdap.class, LocalProxy.class));
-  }
-
-  private static final class LocalProxy extends MechanismProxy<AuthnMechLdap> {
-    boolean enableAuthn;
-    boolean enableGroupLookup;
-    String hostport;
-    String bindDn;
-    String password;
-    String searchBase;
-    String userSearchFilter;
-    String groupSearchFilter;
-    int sslSupport;
-    int supportedAuthMethods;
-    long trustDuration = DEFAULT_TRUST_DURATION;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(AuthnMechLdap mechanism) {
-      super(mechanism);
-      hostport = mechanism.getHostport();
-      bindDn = mechanism.getBindDn();
-      password = mechanism.getPassword();
-      searchBase = mechanism.getSearchBase();
-      userSearchFilter = mechanism.getUserSearchFilter();
-      groupSearchFilter = mechanism.getGroupSearchFilter();
-      sslSupport = mechanism.getSslSupport();
-      supportedAuthMethods = mechanism.getSupportedAuthMethods();
-      enableAuthn = mechanism.isEnableAuthn();
-      enableGroupLookup = mechanism.isEnableGroupLookup();
-      trustDuration = mechanism.getTrustDuration();
-    }
-
-    @Override
-    public AuthnMechLdap build() {
-      return make(name, hostport, bindDn, password, searchBase, userSearchFilter, groupSearchFilter,
-          sslSupport, supportedAuthMethods, enableAuthn, enableGroupLookup, trustDuration);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechNtlm.java b/src/com/google/enterprise/secmgr/config/AuthnMechNtlm.java
deleted file mode 100644
index 035810b..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechNtlm.java
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The configuration of an NTLM authentication mechanism.
- */
-@Immutable
-public final class AuthnMechNtlm extends AuthnMechanism {
-
-  public static final String TYPE_NAME = "NTLM";
-  private static final long DEFAULT_TRUST_DURATION = 20 * 60 * 1000;  // 20 mins
-
-  private final String sampleUrl;
-  private final long trustDuration;
-
-  /**
-   * Make a new NTLM mechanism.
-   *
-   * @param sampleUrl A sample URL that requires NTLM authentication.
-   * @param trustDuration The number of milliseconds that successfully
-   *     verified credentials are trusted.  This must be a non-negative number.
-   * @return A new mechanism with the given elements.
-   */
-  public static AuthnMechNtlm make(String name, String sampleUrl, long trustDuration) {
-    return new AuthnMechNtlm(name, sampleUrl, trustDuration);
-  }
-
-  /**
-   * Make a new NTLM mechanism with a default trust duration.
-   *
-   * @param sampleUrl A sample URL that requires NTLM authentication.
-   * @return A new mechanism with the given elements.
-   */
-  public static AuthnMechNtlm make(String name, String sampleUrl) {
-    return make(name, sampleUrl, getDefaultTrustDuration());
-  }
-
-  private AuthnMechNtlm(String name, String sampleUrl, long trustDuration) {
-    super(name);
-    this.sampleUrl = checkString(sampleUrl);
-    this.trustDuration = checkTrustDuration(trustDuration);
-  }
-
-  /**
-   * Make a new unconfigured NTLM mechanism.
-   */
-  public static AuthnMechNtlm makeEmpty() {
-    return new AuthnMechNtlm();
-  }
-
-  private AuthnMechNtlm() {
-    super();
-    this.sampleUrl = null;
-    this.trustDuration = getDefaultTrustDuration();
-  }
-
-  @Override
-  public String getTypeName() {
-    return TYPE_NAME;
-  }
-
-  /**
-   * Get the default trust-duration value.
-   */
-  public static long getDefaultTrustDuration() {
-    return DEFAULT_TRUST_DURATION;
-  }
-
-  @Override
-  public List<CredentialTransform> getCredentialTransforms() {
-    return ImmutableList.of(
-        CredentialTransform.make(
-            CredentialTypeSet.PRINCIPAL_AND_PASSWORD,
-            CredentialTypeSet.VERIFIED_PRINCIPAL_AND_PASSWORD));
-  }
-
-  @Override
-  public AuthnMechanism copyWithNewName(String name) {
-    return make(name, getSampleUrl(), getTrustDuration());
-  }
-
-  @Override
-  public String getSampleUrl() {
-    return sampleUrl;
-  }
-
-  @Override
-  public long getTrustDuration() {
-    return trustDuration;
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof AuthnMechNtlm)) { return false; }
-    AuthnMechNtlm mech = (AuthnMechNtlm) object;
-    return super.equals(mech)
-        && Objects.equal(getSampleUrl(), mech.getSampleUrl())
-        && Objects.equal(getTrustDuration(), mech.getTrustDuration());
-  }
-
-  @Override
-  public int hashCode() {
-    return super.hashCode(getSampleUrl(), getTrustDuration());
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(AuthnMechNtlm.class,
-        ProxyTypeAdapter.make(AuthnMechNtlm.class, LocalProxy.class));
-  }
-
-  private static final class LocalProxy extends MechanismProxy<AuthnMechNtlm> {
-    String sampleUrl;
-    long trustDuration = DEFAULT_TRUST_DURATION;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(AuthnMechNtlm mechanism) {
-      super(mechanism);
-      sampleUrl = mechanism.getSampleUrl();
-      trustDuration = mechanism.getTrustDuration();
-    }
-
-    @Override
-    public AuthnMechNtlm build() {
-      return make(name, sampleUrl, trustDuration);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechSaml.java b/src/com/google/enterprise/secmgr/config/AuthnMechSaml.java
deleted file mode 100644
index 529624c..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechSaml.java
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The configuration of a SAML authentication mechanism.
- */
-@Immutable
-public final class AuthnMechSaml extends AuthnMechanism {
-
-  public static final String TYPE_NAME = "SAML";
-
-  private final String entityId;
-
-  public static AuthnMechSaml make(String name, String entityId) {
-    return new AuthnMechSaml(name, entityId);
-  }
-
-  private AuthnMechSaml(String name, String entityId) {
-    super(name);
-    this.entityId = checkString(entityId);
-  }
-
-  public static AuthnMechSaml makeEmpty() {
-    return new AuthnMechSaml();
-  }
-
-  private AuthnMechSaml() {
-    super();
-    this.entityId = null;
-  }
-
-  @Override
-  public String getTypeName() {
-    return TYPE_NAME;
-  }
-
-  @Override
-  public List<CredentialTransform> getCredentialTransforms() {
-    return ImmutableList.of(
-        CredentialTransform.make(CredentialTypeSet.NONE, CredentialTypeSet.VERIFIED_PRINCIPAL));
-  }
-
-  @Override
-  public AuthnMechanism copyWithNewName(String name) {
-    return make(name, getEntityId());
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof AuthnMechSaml)) { return false; }
-    AuthnMechSaml mech = (AuthnMechSaml) object;
-    return super.equals(mech)
-        && Objects.equal(entityId, mech.getEntityId());
-  }
-
-  @Override
-  public int hashCode() {
-    return super.hashCode(entityId);
-  }
-
-  /**
-   * Get the SAML entity ID for this authority.  This ID is used as a key when
-   * looking up SAML metadata that describes the authority.
-   *
-   * @return The SAML entity ID as a string, never null or empty, normally a URI.
-   */
-  public String getEntityId() {
-    return entityId;
-  }
-
-  public static final Predicate<AuthnMechanism> SAML_PREDICATE = new Predicate<AuthnMechanism>() {
-    public boolean apply(AuthnMechanism config) {
-      return (config instanceof AuthnMechSaml);
-    }
-  };
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(AuthnMechSaml.class,
-        ProxyTypeAdapter.make(AuthnMechSaml.class, LocalProxy.class));
-  }
-
-  private static final class LocalProxy extends MechanismProxy<AuthnMechSaml> {
-    String entityId;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(AuthnMechSaml mechanism) {
-      super(mechanism);
-      entityId = mechanism.getEntityId();
-    }
-
-    @Override
-    public AuthnMechSaml build() {
-      return make(name, entityId);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechSampleUrl.java b/src/com/google/enterprise/secmgr/config/AuthnMechSampleUrl.java
deleted file mode 100644
index a9a99be..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechSampleUrl.java
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.gson.GsonBuilder;
-
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The configuration of a sample-URL check authentication mechanism.
- */
-@Immutable
-public final class AuthnMechSampleUrl extends AuthnMechanism {
-
-  public static final String TYPE_NAME = "SampleUrlCheck";
-  public static final String DEFAULT_RETURN_URL_PARAMETER = "returnPath";
-  private static final long DEFAULT_TRUST_DURATION = 5 * 60 * 1000;  // five minutes
-
-  private final String sampleUrl;
-  private final String redirectUrl;
-  private final String returnUrlParameter;
-  private final long trustDuration;
-
-  /**
-   * Make a new sample-URL cookie mechanism.
-   *
-   * @param sampleUrl A sample URL that requires cookie authentication.
-   * @param redirectUrl A URL to redirect the user agent to in order to get the cookie(s).
-   * @param trustDuration The number of milliseconds that successfully
-   *     verified credentials are trusted.  This must be a non-negative number.
-   * @return A new mechanism with the given elements.
-   */
-  public static AuthnMechSampleUrl make(String name, String sampleUrl, String redirectUrl,
-      String returnUrlParameter, long trustDuration) {
-    return new AuthnMechSampleUrl(name, sampleUrl, redirectUrl, returnUrlParameter, trustDuration);
-  }
-
-  /**
-   * Make a new sample-URL cookie mechanism with a default trust duration.
-   *
-   * @param sampleUrl A sample URL that requires cookie authentication.
-   * @param redirectUrl A URL to redirect the user agent to in order to get the cookie(s).
-   * @return A new mechanism with the given elements.
-   */
-  public static AuthnMechSampleUrl make(String name, String sampleUrl, String redirectUrl) {
-    return make(name, sampleUrl, redirectUrl, getDefaultReturnUrlParameter(),
-        getDefaultTrustDuration());
-  }
-
-  private AuthnMechSampleUrl(String name, String sampleUrl, String redirectUrl,
-      String returnUrlParameter, long trustDuration) {
-    super(name);
-    this.sampleUrl = checkStringOrNull(sampleUrl);
-    this.redirectUrl = checkStringOrNull(redirectUrl);
-    this.returnUrlParameter = checkStringOrNull(returnUrlParameter);
-    this.trustDuration = checkTrustDuration(trustDuration);
-  }
-
-  /**
-   * Make a new unconfigured sample-URL cookie mechanism.
-   */
-  public static AuthnMechSampleUrl makeEmpty() {
-    return new AuthnMechSampleUrl();
-  }
-
-  private AuthnMechSampleUrl() {
-    super();
-    this.sampleUrl = null;
-    this.redirectUrl = null;
-    this.returnUrlParameter = getDefaultReturnUrlParameter();
-    this.trustDuration = getDefaultTrustDuration();
-  }
-
-  @Override
-  public String getTypeName() {
-    return TYPE_NAME;
-  }
-
-  public static String getDefaultReturnUrlParameter() {
-    return DEFAULT_RETURN_URL_PARAMETER;
-  }
-
-  /**
-   * Get the default trust-duration value.
-   */
-  public static long getDefaultTrustDuration() {
-    return DEFAULT_TRUST_DURATION;
-  }
-
-  @Override
-  public List<CredentialTransform> getCredentialTransforms() {
-    if (redirectUrl != null) {
-      return ImmutableList.of();
-    }
-    return ImmutableList.of(
-        CredentialTransform.make(CredentialTypeSet.COOKIES, CredentialTypeSet.VERIFIED_PRINCIPAL),
-        CredentialTransform.make(CredentialTypeSet.COOKIES, CredentialTypeSet.VERIFIED_ALIASES),
-        CredentialTransform.make(CredentialTypeSet.COOKIES, CredentialTypeSet.VERIFIED_GROUPS));
-  }
-
-  @Override
-  public AuthnMechanism copyWithNewName(String name) {
-    return make(name, getSampleUrl(), getRedirectUrl(), getReturnUrlParameter(),
-        getTrustDuration());
-  }
-
-  @Override
-  public String getSampleUrl() {
-    return sampleUrl;
-  }
-
-  /**
-   * Gets the redirect URL associated with this authority.
-   *
-   * @return The redirect URL as a string, or {@code null} if none exists.
-   */
-  public String getRedirectUrl() {
-    return redirectUrl;
-  }
-
-  /**
-   * Gets the return-URL parameter associated with this authority.
-   *
-   * This is the name of the request/CGI param we set on an outbound redirect,
-   * which tells the server on the receiving end of the redirect where to
-   * redirect back to once it's done.
-   *
-   * The default value for this is {@code "returnPath"}.
-   *
-   * @return The return url parameter string, or {@code null} for default.
-   */
-  public String getReturnUrlParameter() {
-    return returnUrlParameter;
-  }
-
-  @Override
-  public long getTrustDuration() {
-    return trustDuration;
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof AuthnMechSampleUrl)) { return false; }
-    AuthnMechSampleUrl mech = (AuthnMechSampleUrl) object;
-    return super.equals(mech)
-        && Objects.equal(getSampleUrl(), mech.getSampleUrl())
-        && Objects.equal(getRedirectUrl(), mech.getRedirectUrl())
-        && Objects.equal(getReturnUrlParameter(), mech.getReturnUrlParameter())
-        && Objects.equal(getTrustDuration(), mech.getTrustDuration());
-  }
-
-  @Override
-  public int hashCode() {
-    return super.hashCode(getSampleUrl(), getRedirectUrl(), getReturnUrlParameter(),
-        getTrustDuration());
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(AuthnMechSampleUrl.class,
-        ProxyTypeAdapter.make(AuthnMechSampleUrl.class, LocalProxy.class));
-  }
-
-  private static final class LocalProxy extends MechanismProxy<AuthnMechSampleUrl> {
-    String sampleUrl;
-    String redirectUrl;
-    String returnUrlParameter = DEFAULT_RETURN_URL_PARAMETER;
-    long trustDuration = DEFAULT_TRUST_DURATION;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(AuthnMechSampleUrl mechanism) {
-      super(mechanism);
-      sampleUrl = mechanism.getSampleUrl();
-      redirectUrl = mechanism.getRedirectUrl();
-      returnUrlParameter = mechanism.getReturnUrlParameter();
-      trustDuration = mechanism.getTrustDuration();
-    }
-
-    @Override
-    public AuthnMechSampleUrl build() {
-      return make(name, sampleUrl, redirectUrl, returnUrlParameter, trustDuration);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthnMechanism.java b/src/com/google/enterprise/secmgr/config/AuthnMechanism.java
deleted file mode 100644
index 5754e81..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthnMechanism.java
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.List;
-import java.util.Locale;
-import java.util.regex.Pattern;
-
-import javax.annotation.concurrent.ThreadSafe;
-
-/**
- * The configuration of an authentication mechanism.  This is the base class for
- * all mechanisms; individual mechanisms inherit from here.
- */
-@ThreadSafe
-public abstract class AuthnMechanism {
-  private static final int CONFIG_NAME_MAX_LENGTH = 200;
-  private static final Pattern CONFIG_NAME_PATTERN
-      = Pattern.compile("^[a-zA-Z0-9_][a-zA-Z0-9_-]*$");
-
-  private final String name;
-  private final AuthnAuthority authority;
-
-  protected AuthnMechanism() {
-    name = null;
-    authority = AuthnAuthority.make();
-  }
-
-  protected AuthnMechanism(String name) {
-    // TODO(cph): eliminate name == null once all callers supply real names.
-    // Right now the only callers with name == null are unit tests.
-    this.name = name;
-    if (name == null) {
-      authority = AuthnAuthority.make();
-    } else {
-      Preconditions.checkArgument(isValidConfigName(name), "Invalid mechanism name: %s", name);
-      authority = AuthnAuthority.make(name);
-    }
-  }
-
-  /**
-   * Is a given string a valid name for a mechanism or credential group?  A
-   * valid name is between 1 and 200 characters and consists only of ASCII
-   * alphanumerics, the underscore character, and the hyphen character.  The
-   * first character may not be a hyphen.
-   *
-   * @param name The string to test for validity.
-   * @return True only if the string is valid.
-   */
-  public static boolean isValidConfigName(String name) {
-    return name != null
-        && !name.isEmpty()
-        && name.length() <= CONFIG_NAME_MAX_LENGTH
-        && CONFIG_NAME_PATTERN.matcher(name).matches();
-  }
-
-  /**
-   * Check a string argument that's allowed to be null.  Disallows empty
-   * strings.  May return a modified string; e.g. may run .trim() on the
-   * argument.
-   *
-   * @param string The string to check.
-   * @return A checked string that is possibly different from the argument.
-   * @throws IllegalArgumentException if the input string is empty.
-   */
-  protected static String checkStringOrNull(String string) {
-    Preconditions.checkArgument(string == null || !string.isEmpty());
-    return string;
-  }
-
-  /**
-   * Check a string argument.  Disallows null and empty strings.  May return a
-   * modified string; e.g. may run .trim() on the argument.
-   *
-   * @param string The string to check.
-   * @return A checked string that is possibly different from the argument.
-   * @throws IllegalArgumentException if the input string is null or empty.
-   */
-  protected static String checkString(String string) {
-    Preconditions.checkArgument(string != null && !string.isEmpty());
-    return string;
-  }
-
-  /**
-   * Check a URL string argument.  Disallows null and non-well-formed strings.
-   * May return a modified string; e.g. may run .trim() on the argument.
-   *
-   * @param string The URL string to check.
-   * @return A checked URL string that is possibly different from the argument.
-   * @throws IllegalArgumentException if the input string is null or not well formed.
-   */
-  protected static String checkUrlString(String string) {
-    try {
-      return (new URL(checkString(string))).toString();
-    } catch (MalformedURLException e) {
-      throw new IllegalArgumentException(e);
-    }
-  }
-
-  /**
-   * Check a trust-duration argument.
-   *
-   * @param trustDuration The trust-duration argument to check.
-   * @return A checked value.
-   * @throws IllegalArgumentException if the argument is invalid.
-   */
-  protected static long checkTrustDuration(long trustDuration) {
-    Preconditions.checkArgument(trustDuration >= 0);
-    return trustDuration;
-  }
-
-  /**
-   * Get the type name of the mechanism.
-   *
-   * @return The type name, never null or empty.
-   */
-  public abstract String getTypeName();
-
-  /**
-   * @return An immutable list of the transformations this mechanism implements.
-   */
-  public abstract List<CredentialTransform> getCredentialTransforms();
-
-  /**
-   * Can this mechanism use ULF credentials?
-   */
-  public boolean canUseUlfCredentials() {
-    return Iterables.any(getCredentialTransforms(),
-        new Predicate<CredentialTransform>() {
-          public boolean apply(CredentialTransform credentialTransform) {
-            CredentialTypeSet inputs = credentialTransform.getInputs();
-            return !inputs.getAreVerified()
-                && inputs.getElements().containsAll(
-                    CredentialTypeSet.PRINCIPAL_AND_PASSWORD.getElements());
-          }
-        });
-  }
-
-  /**
-   * Return a copy of the current mechanism, with a given name.
-   *
-   * @param name The new name.
-   * @return A copy of the current mechanism with the new name.
-   */
-  public abstract AuthnMechanism copyWithNewName(String name);
-
-  /**
-   * @return This mechanism's name.
-   */
-  public String getName() {
-    return name;
-  }
-
-  /**
-   * @return This mechanism's authority.
-   */
-  public AuthnAuthority getAuthority() {
-    return authority;
-  }
-
-  public static Function<AuthnMechanism, AuthnAuthority> getAuthorityFunction() {
-    return AUTHORITY_FUNCTION;
-  }
-
-  private static final Function<AuthnMechanism, AuthnAuthority> AUTHORITY_FUNCTION
-      = new Function<AuthnMechanism, AuthnAuthority>() {
-          @Override
-          public AuthnAuthority apply(AuthnMechanism mechanism) {
-            return mechanism.getAuthority();
-          }
-        };
-
-  /**
-   * A sample URL to GET for credential verification.
-   *
-   * @return The mechanism's sample URL as a string, or null if none.
-   */
-  public String getSampleUrl() {
-    throw new UnsupportedOperationException();
-  }
-
-  /**
-   * For how many milliseconds does this mechanism trust newly-verified
-   * credentials?
-   *
-   * @return The number of milliseconds, always a non-negative number.
-   */
-  public long getTrustDuration() {
-    throw new UnsupportedOperationException();
-  }
-
-  protected boolean equals(AuthnMechanism other) {
-    return getName() == null
-        || other.getName() == null
-        || getName().equalsIgnoreCase(other.getName());
-  }
-
-  protected int hashCode(Object... objects) {
-    Object[] copy = new Object[objects.length + 1];
-    copy[0] = (getName() != null)
-        ? getName().toLowerCase(Locale.US)
-        : null;
-    for (int i = 0; i < objects.length; i += 1) {
-      copy[i + 1] = objects[i];
-    }
-    return Objects.hashCode(copy);
-  }
-
-  @Override
-  public String toString() {
-    return ConfigSingleton.getGson().toJson(this);
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(AuthnMechanism.class,
-        TypeAdapters.dispatch(
-            ImmutableList.of(
-                AuthnMechBasic.class,
-                AuthnMechClient.class,
-                AuthnMechConnector.class,
-                AuthnMechForm.class,
-                AuthnMechKerberos.class,
-                AuthnMechLdap.class,
-                AuthnMechNtlm.class,
-                AuthnMechSaml.class,
-                AuthnMechSampleUrl.class)));
-  }
-
-  /** A base class for type proxies of sub-classes. */
-  protected abstract static class MechanismProxy<T extends AuthnMechanism>
-      implements TypeProxy<T> {
-    public String name;
-
-    protected MechanismProxy() {
-    }
-
-    protected MechanismProxy(AuthnMechanism mechanism) {
-      name = mechanism.getName();
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/AuthzMechanism.java b/src/com/google/enterprise/secmgr/config/AuthzMechanism.java
deleted file mode 100644
index fd80ce1..0000000
--- a/src/com/google/enterprise/secmgr/config/AuthzMechanism.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.config;
-
-/**
- * @author meghna@google.com (Meghna Dhar)
- */
-public enum AuthzMechanism {
-  CACHE,
-  CONNECTOR,
-  DENY,
-  HEADREQUEST,
-  POLICY,
-  SAML,
-}
diff --git a/src/com/google/enterprise/secmgr/config/ConfigCodec.java b/src/com/google/enterprise/secmgr/config/ConfigCodec.java
deleted file mode 100644
index f0aaa6a..0000000
--- a/src/com/google/enterprise/secmgr/config/ConfigCodec.java
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2008 Google Inc.
-//
-// 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.secmgr.config;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-
-/**
- * A base class for implementing a configuration encode/decode class.
- */
-public abstract class ConfigCodec {
-
-  /**
-   * Decode a configuration from a string.
-   *
-   * @param string The string to decode.
-   * @return A configuration.
-   * @throws IOException if there are errors while reading the configuration.
-   * @throws ConfigException if the configuration is malformed.
-   */
-  public SecurityManagerConfig readConfig(String string)
-      throws IOException, ConfigException {
-    return readConfig(new StringReader(string));
-  }
-
-  /**
-   * Encode a configuration as a string.
-   *
-   * @param config The configuration to be encoded.
-   * @return The encoded string.
-   * @throws IOException if there are errors while writing the configuration.
-   */
-  public String configToString(SecurityManagerConfig config) throws IOException {
-    Writer writer = new StringWriter();
-    writeConfig(config, writer);
-    return writer.toString();
-  }
-
-  /**
-   * Read and decode a configuration from a given source.
-   *
-   * @param reader The source to read the encoded configuration from.
-   * @return A configuration.
-   * @throws IOException if there are errors while reading the configuration.
-   * @throws ConfigException if the configuration is malformed.
-   */
-  public SecurityManagerConfig readConfig(Reader reader)
-      throws IOException, ConfigException {
-    SecurityManagerConfig config = readConfigInternal(reader);
-    guaranteeValidConfig(config);
-    return config;
-  }
-
-  /**
-   * Read and decode a configuration from a given file.
-   *
-   * @param file The file to read the encoded configuration from.
-   * @return A configuration.
-   * @throws IOException if there are errors while reading the configuration.
-   * @throws ConfigException if the configuration is malformed.
-   */
-  public SecurityManagerConfig readConfig(File file)
-      throws IOException, ConfigException {
-    Reader reader = new FileReader(file);
-    try {
-      return readConfig(reader);
-    } finally {
-      reader.close();
-    }
-  }
-
-  protected abstract SecurityManagerConfig readConfigInternal(Reader reader)
-      throws IOException, ConfigException;
-
-  /**
-   * Encode and write a configuration to a given sink.
-   *
-   * @param config The configuration to be encoded.
-   * @param writer The sink to write the encoded configuration to.
-   * @throws IOException if there are errors while writing the configuration.
-   */
-  public void writeConfig(SecurityManagerConfig config, Writer writer) throws IOException {
-    guaranteeValidConfig(config);
-    writeConfigInternal(config, writer);
-  }
-
-  protected abstract void writeConfigInternal(SecurityManagerConfig config, Writer writer)
-      throws IOException;
-
-  private void guaranteeValidConfig(SecurityManagerConfig config) {
-    if (!isValidConfig(config)) {
-      throw new IllegalStateException("Config is not valid: " + config);
-    }
-  }
-
-  /**
-   * A valid config must contain a "default" group and that group must require a
-   * username, be non-optional, and non-empty.  This in turn ensures that a saml
-   * assertion from the security manager will always contain a username which
-   * can in turn be used when creating policy ACLs.
-   *
-   * TODO(martincochran): ensure that EFE gets the right username and/or that
-   * the correct saml subject is generated by the security manager.
-   */
-  private boolean isValidConfig(SecurityManagerConfig config) {
-
-    return true;
-    /* TODO(kstillson): I'm disabling this check.  It was added to address
-     * to address the concern that PVI assignment may not be stable- specifically,
-     * user1 has a forms auth cookie before any interaction with the GSA, if the
-     * default CG does not insist on requires-username, then CG will be satisfied
-     * but no username is set, so the PVI could come from somewhere else (e.g.
-     * kerberos).  However, user2 has no cookie, so they get a ULF, and the PVI
-     * is set by their forms login.  That is a problem, however, this solution
-     * is too drastic, and eliminates numerous valid use-cases (such as a sec-mgr
-     * that does nothing but a single forms-auth CG that doesn't need a username).
-     * So We're going to have to find a more subtle solution to the original
-     * problem.
-
-    if (config.isEmpty()) {
-      return true;
-    }
-    boolean defaultGroupEmpty = false;
-    boolean someGroupNonEmpty = false;
-
-    for (CredentialsGroup group : config) {
-      if ("default".equalsIgnoreCase(group.getName())) {
-        if (!group.getRequiresUsername()) {
-          return false;
-        }
-        if (group.getIsOptional()) {
-          return false;
-        }
-        if (!group.getElements().isEmpty()) {
-          return true;
-        }
-      }
-      if (!group.getElements().isEmpty()) {
-        someGroupNonEmpty = true;
-      }
-    }
-    return !someGroupNonEmpty;
-    */
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/ConfigException.java b/src/com/google/enterprise/secmgr/config/ConfigException.java
deleted file mode 100644
index 89418ea..0000000
--- a/src/com/google/enterprise/secmgr/config/ConfigException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.config;
-
-/**
- * An exception that's thrown when a {@link ConfigCodec} has trouble parsing a
- * configuration string.
- */
-public class ConfigException extends Exception {
-
-  public ConfigException(String message) { super(message); }
-
-  public ConfigException(Throwable e) { super(e); }
-
-  public ConfigException(String message, Throwable e) { super(message, e); }
-}
diff --git a/src/com/google/enterprise/secmgr/config/ConfigModule.java b/src/com/google/enterprise/secmgr/config/ConfigModule.java
deleted file mode 100644
index fd55612..0000000
--- a/src/com/google/enterprise/secmgr/config/ConfigModule.java
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.gson.GsonBuilder;
-/*import com.google.inject.AbstractModule;
-import com.google.inject.name.Names;*/
-
-/**
- * Guice configuration for this package.
- */
-public final class ConfigModule /*extends AbstractModule*/ {
-
-  private final String configFilename;
-
-  public ConfigModule(String configFilename) {
-    this.configFilename = configFilename;
-  }
-
-/*  @Override
-  protected void configure() {
-    bind(ConfigCodec.class).to(JsonConfig.class);
-    bind(ConfigSingleton.class);
-    bind(FlexAuthorizer.class).to(FlexAuthorizerImpl.class);
-    bindConstant()
-        .annotatedWith(Names.named("configFile"))
-        .to(configFilename);
-    requestStaticInjection(ConfigSingleton.class);
-  }*/
-
-  public static void registerTypeAdapters(GsonBuilder builder) {
-    AuthnAuthority.registerTypeAdapters(builder);
-    AuthnMechBasic.registerTypeAdapters(builder);
-    AuthnMechClient.registerTypeAdapters(builder);
-    AuthnMechConnector.registerTypeAdapters(builder);
-    AuthnMechForm.registerTypeAdapters(builder);
-    AuthnMechKerberos.registerTypeAdapters(builder);
-    AuthnMechLdap.registerTypeAdapters(builder);
-    AuthnMechNtlm.registerTypeAdapters(builder);
-    AuthnMechSaml.registerTypeAdapters(builder);
-    AuthnMechSampleUrl.registerTypeAdapters(builder);
-    AuthnMechanism.registerTypeAdapters(builder);
-    ConfigParams.registerTypeAdapters(builder);
-    ConnMgrInfo.registerTypeAdapters(builder);
-    CredentialGroup.registerTypeAdapters(builder);
-    FlexAuthorizerImpl.registerTypeAdapters(builder);
-    FlexAuthzRoutingTableEntry.registerTypeAdapters(builder);
-    FlexAuthzRule.registerTypeAdapters(builder);
-    ParamName.registerTypeAdapters(builder);
-    SecurityManagerConfig.registerTypeAdapters(builder);
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/ConfigParams.java b/src/com/google/enterprise/secmgr/config/ConfigParams.java
deleted file mode 100644
index c8a8aae..0000000
--- a/src/com/google/enterprise/secmgr/config/ConfigParams.java
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-
-import java.lang.reflect.Type;
-import java.util.EnumSet;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * An generalized configuration-parameters implementation.  This can store any
- * named parameter, of any type.
- *
- * @see ParamName
- */
-@Immutable
-public final class ConfigParams {
-
-  private final ImmutableMap<ParamName, Object> map;
-
-  private ConfigParams(ImmutableMap<ParamName, Object> map) {
-    this.map = map;
-  }
-
-  /**
-   * Gets the set of keys.
-   *
-   * @return The keys.
-   */
-  public static EnumSet<ParamName> keySet() {
-    return EnumSet.allOf(ParamName.class);
-  }
-
-  /**
-   * Gets the value of a parameter.
-   *
-   * @param key The name of the parameter to retrieve.
-   * @return The value of the parameter.
-   */
-  public Object get(ParamName key) {
-    return map.get(key);
-  }
-
-  /**
-   * Gets the value of a parameter, casting it to a given type.
-   *
-   * @param key The name of the parameter to retrieve.
-   * @param valueClass The class to cast the value to.
-   * @return The value of the parameter.
-   * @throws IllegalArgumentException if <code>valueClass</code> isn't
-   *     assignable from the parameter's value.
-   */
-  public <T> T get(ParamName key, Class<T> valueClass) {
-    Preconditions.checkArgument(valueClass.isAssignableFrom(key.getValueClass()));
-    return valueClass.cast(get(key));
-  }
-
-  /**
-   * Gets a default set of configuration parameters.
-   *
-   * @return The default set.
-   */
-  public static ConfigParams makeDefault() {
-    return builder().build();
-  }
-
-  /**
-   * Gets a new configuration-parameters builder.
-   *
-   * @return A new builder.
-   */
-  public static Builder builder() {
-    return new Builder(null);
-  }
-
-  /**
-   * Gets a new configuration-parameters builder initialized with defaults.
-   *
-   * @param defaultValues A set of configuration parameters to use as defaults.
-   * @return A new builder.
-   */
-  public static Builder builder(ConfigParams defaultValues) {
-    Preconditions.checkNotNull(defaultValues);
-    return new Builder(defaultValues);
-  }
-
-  /**
-   * A builder factory for configuration parameters.
-   */
-  public static final class Builder {
-    private final ConfigParams defaultValues;
-    private final ImmutableMap.Builder<ParamName, Object> mapBuilder;
-    private final EnumSet<ParamName> unseen;
-
-    private Builder(ConfigParams defaultValues) {
-      this.defaultValues = defaultValues;
-      mapBuilder = ImmutableMap.builder();
-      unseen = EnumSet.allOf(ParamName.class);
-    }
-
-    /**
-     * Set the value of a parameter.
-     *
-     * @param key The parameter's name.
-     * @param value The parameter's value.
-     * @return This builder, for programming convenience.
-     * @throws IllegalArgumentException if the value isn't valid for this parameter.
-     */
-    public Builder put(ParamName key, Object value) {
-      Preconditions.checkArgument(key.isValidValue(value));
-      mapBuilder.put(key, value);
-      unseen.remove(key);
-      return this;
-    }
-
-    /**
-     * @return The completed parameters object.
-     */
-    public ConfigParams build() {
-      for (ParamName key : unseen) {
-        mapBuilder.put(key,
-            (defaultValues == null)
-            ? key.getDefaultValue()
-            : defaultValues.get(key));
-      }
-      return new ConfigParams(mapBuilder.build());
-    }
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof ConfigParams)) { return false; }
-    ConfigParams other = (ConfigParams) object;
-    for (ParamName key : keySet()) {
-      if (!get(key).equals(other.get(key))) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  @Override
-  public int hashCode() {
-    EnumSet<ParamName> keys = keySet();
-    Object[] values = new Object[keys.size()];
-    int i = 0;
-    for (ParamName key : keys) {
-      values[i++] = get(key);
-    }
-    return Objects.hashCode(values);
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(ConfigParams.class, new LocalTypeAdapter());
-  }
-
-  static final class LocalTypeAdapter
-      implements JsonSerializer<ConfigParams>, JsonDeserializer<ConfigParams> {
-    LocalTypeAdapter() {
-    }
-
-    @Override
-    public JsonElement serialize(ConfigParams params, Type type, JsonSerializationContext context) {
-      JsonObject jo = new JsonObject();
-      for (ParamName key : ConfigParams.keySet()) {
-        jo.add(key.toString(), context.serialize(params.get(key), key.getValueClass()));
-      }
-      return jo;
-    }
-
-    @Override
-    public ConfigParams deserialize(JsonElement src, Type type,
-        JsonDeserializationContext context) {
-      JsonObject jo = src.getAsJsonObject();
-      ConfigParams.Builder builder = ConfigParams.builder();
-      for (ParamName key : ConfigParams.keySet()) {
-        JsonElement je = jo.get(key.toString());
-        if (je != null) {
-          builder.put(key, context.deserialize(je, key.getValueClass()));
-        }
-      }
-      return builder.build();
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/ConfigSingleton.java b/src/com/google/enterprise/secmgr/config/ConfigSingleton.java
index 8853daa..d445578 100644
--- a/src/com/google/enterprise/secmgr/config/ConfigSingleton.java
+++ b/src/com/google/enterprise/secmgr/config/ConfigSingleton.java
@@ -16,22 +16,11 @@
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.enterprise.secmgr.common.FileUtil;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Key;
-import com.google.inject.Singleton;
-import com.google.inject.TypeLiteral;
-import com.google.inject.name.Named;
 
-import java.io.File;
-import java.io.IOException;
 import java.util.Observable;
 import java.util.Observer;
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.annotation.concurrent.GuardedBy;
@@ -40,14 +29,11 @@
 /**
  * A singleton class to access configured parameters.
  */
-@Singleton
 @ThreadSafe
 public class ConfigSingleton {
   private static final Logger LOGGER = Logger.getLogger(ConfigSingleton.class.getName());
 
-  @Inject private static Injector injector;
-  @Inject private static ConfigSingleton instance;
-  @GuardedBy("class") private static SecurityManagerConfig configOverride = null;
+  private static ConfigSingleton instance;
   @GuardedBy("class") private static Gson gson;
   private static final LocalObservable observable = new LocalObservable();
 
@@ -58,58 +44,16 @@
     }
   }
 
-  private final ConfigCodec configCodec;
-  private final String configFilename;
-  /** The modification time of the configuration file when last read. */
-  @GuardedBy("this") private long configTime;
-  /** The parsed configuration file. */
-  @GuardedBy("this") private SecurityManagerConfig config;
-
-  @Inject
-  private ConfigSingleton(ConfigCodec configCodec, @Named("configFile") String configFilename) {
-    Preconditions.checkNotNull(configCodec);
-    Preconditions.checkArgument(!Strings.isNullOrEmpty(configFilename));
-    this.configCodec = configCodec;
-    this.configFilename = configFilename;
+  private ConfigSingleton() {
     resetInternal();
   }
 
-  /**
-   * @return The application's Guice injector.
-   */
-  public static Injector getInjector() {
-    return injector;
-  }
-
-  /**
-   * A convenience method that invokes the injector.
-   *
-   * @param clazz The class to instantiate.
-   * @return An instance of the given class.
-   */
-  public static <T> T getInstance(Class<T> clazz) {
-    return injector.getInstance(clazz);
-  }
-
-  /**
-   * A convenience method that invokes the injector.
-   *
-   * @param type The type to instantiate.
-   * @return An instance of the given type.
-   */
-  public static <T> T getInstance(TypeLiteral<T> type) {
-    return injector.getInstance(Key.get(type));
-  }
-
   @VisibleForTesting
   public static synchronized void reset() {
-    configOverride = null;
     instance.resetInternal();
   }
 
   private synchronized void resetInternal() {
-    configTime = 0;
-    config = null;
   }
 
   /**
@@ -147,115 +91,4 @@
     Preconditions.checkNotNull(gson);
     return gson;
   }
-
-  /**
-   * @return The current configuration.
-   * @throws IOException if there are I/O errors reading the configuration.
-   */
-  public static synchronized SecurityManagerConfig getConfig()
-      throws IOException {
-    return (configOverride != null) ? configOverride : getConfigNoOverride();
-  }
-
-  @VisibleForTesting
-  public static synchronized SecurityManagerConfig getConfigNoOverride()
-      throws IOException {
-    return instance.getConfigInternal();
-  }
-
-  @VisibleForTesting
-  public static synchronized void setConfig(SecurityManagerConfig config) {
-    configOverride = config;
-    setChanged();
-  }
-
-  private synchronized SecurityManagerConfig getConfigInternal()
-      throws IOException {
-    File file = FileUtil.getContextFile(configFilename);
-    // Check the config file's mod time; if it hasn't changed since the last
-    // successful read, use the cached value.  Otherwise, try reading the config
-    // file.  Go around the loop until the mod time before the read and the mod
-    // time after the read are the same.  This detects changes to the file
-    // during the read.
-    while (true) {
-      long time = file.lastModified();
-      if (time == 0) {
-        throw new IOException("No such file: " + file);
-      }
-      if (time == configTime) {
-        break;
-      }
-      try {
-        config = configCodec.readConfig(file);
-      } catch (ConfigException e) {
-        LOGGER.log(Level.SEVERE, "Error parsing config file. Returning default config.", e);
-        config = SecurityManagerConfig.makeDefault();
-      }
-      configTime = time;
-      LOGGER.fine("Config:\n" + config);
-      observable.setChanged();
-    }
-    observable.notifyObservers();
-    return config;
-  }
-
-  /** @see SecurityManagerConfig#getAclGroupsFilename */
-  public static String getAclGroupsFilename() throws IOException {
-    return getConfig().getAclGroupsFilename();
-  }
-
-  /** @see SecurityManagerConfig#getAclUrlsFilename */
-  public static String getAclUrlsFilename() throws IOException {
-    return getConfig().getAclUrlsFilename();
-  }
-
-  /** @see SecurityManagerConfig#getCertificateAuthoritiesFilename */
-  public static String getCertificateAuthoritiesFilename() throws IOException {
-    return getConfig().getCertificateAuthoritiesFilename();
-  }
-
-  /** @see SecurityManagerConfig#getConnectorManagerUrls */
-  public static Iterable<String> getConnectorManagerUrls() throws IOException {
-    return getConfig().getConnectorManagerUrls();
-  }
-
-  /** @see SecurityManagerConfig#getDenyRulesFilename */
-  public static String getDenyRulesFilename() throws IOException {
-    return getConfig().getDenyRulesFilename();
-  }
-
-  /** @see SecurityManagerConfig#getGlobalBatchRequestTimeout */
-  public static Float getGlobalBatchRequestTimeout() throws IOException {
-    return getConfig().getGlobalBatchRequestTimeout();
-  }
-
-  /** @see SecurityManagerConfig#getGlobalSingleRequestTimeout */
-  public static Float getGlobalSingleRequestTimeout() throws IOException {
-    return getConfig().getGlobalSingleRequestTimeout();
-  }
-
-  /** @see SecurityManagerConfig#getSamlMetadataFilename */
-  public static String getSamlMetadataFilename() throws IOException {
-    return getConfig().getSamlMetadataFilename();
-  }
-
-  /** @see SecurityManagerConfig#getServerCertificateFilename */
-  public static String getServerCertificateFilename() throws IOException {
-    return getConfig().getServerCertificateFilename();
-  }
-
-  /** @see SecurityManagerConfig#getSigningCertificateFilename */
-  public static String getSigningCertificateFilename() throws IOException {
-    return getConfig().getSigningCertificateFilename();
-  }
-
-  /** @see SecurityManagerConfig#getSigningKeyFilename */
-  public static String getSigningKeyFilename() throws IOException {
-    return getConfig().getSigningKeyFilename();
-  }
-
-  /** @see SecurityManagerConfig#getStunnelPort */
-  public static int getStunnelPort() throws IOException {
-    return getConfig().getStunnelPort();
-  }
 }
diff --git a/src/com/google/enterprise/secmgr/config/ConnMgrInfo.java b/src/com/google/enterprise/secmgr/config/ConnMgrInfo.java
deleted file mode 100644
index 74079eb..0000000
--- a/src/com/google/enterprise/secmgr/config/ConnMgrInfo.java
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * A structure describing a set of configured connector managers.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public final class ConnMgrInfo {
-
-  /**
-   * A structure describing a single connector manager.
-   */
-  @Immutable
-  @ParametersAreNonnullByDefault
-  public static final class Entry {
-    @Nonnull private final String name;
-    @Nonnull private final String url;
-
-    private Entry(String name, String url) {
-      this.name = name;
-      this.url = url;
-    }
-
-    /**
-     * Makes a new connector-manager entry.
-     *
-     * @param name The name of the connector manager.
-     * @param url The URL for the connector manager.
-     * @return An entry containing the above information.
-     */
-    @Nonnull
-    public static Entry make(String name, String url) {
-      Preconditions.checkNotNull(name);
-      Preconditions.checkNotNull(url);
-      return new Entry(name, url);
-    }
-
-    /**
-     * Gets the name of the connector manager represented by this entry.
-     *
-     * @return The connector-manager name.
-     */
-    @Nonnull
-    public String getName() {
-      return name;
-    }
-
-    /**
-     * Gets the URL of the connector manager represented by this entry.
-     *
-     * @return The connector-manager URL as a string.
-     */
-    @Nonnull
-    public String getUrl() {
-      return url;
-    }
-
-    @Override
-    public boolean equals(Object object) {
-      if (object == this) { return true; }
-      if (!(object instanceof Entry)) { return false; }
-      Entry other = (Entry) object;
-      return Objects.equal(getName(), other.getName())
-          && Objects.equal(getUrl(), other.getUrl());
-    }
-
-    @Override
-    public int hashCode() {
-      return Objects.hashCode(getName(), getUrl());
-    }
-
-    @Override
-    public String toString() {
-      return ConfigSingleton.getGson().toJson(this);
-    }
-  }
-
-  @Nonnull private final ImmutableSet<Entry> entries;
-
-  private ConnMgrInfo(ImmutableSet<Entry> entries) {
-    this.entries = entries;
-  }
-
-  /**
-   * Makes a new connector-manager info object.
-   *
-   * @param entries The per-connector-manager entries.
-   * @return A new set with the given entries.
-   */
-  @Nonnull
-  public static ConnMgrInfo make(Iterable<Entry> entries) {
-    return new ConnMgrInfo(ImmutableSet.copyOf(entries));
-  }
-
-  /**
-   * Gets the per-connector-manager entries for this object.
-   *
-   * @return The entries as an immutable set.
-   */
-  @Nonnull
-  public ImmutableSet<Entry> getEntries() {
-    return entries;
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof ConnMgrInfo)) { return false; }
-    ConnMgrInfo other = (ConnMgrInfo) object;
-    return Objects.equal(getEntries(), other.getEntries());
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hashCode(getEntries());
-  }
-
-  @Override
-  public String toString() {
-    return ConfigSingleton.getGson().toJson(this);
-  }
-
-  /**
-   * Decodes string-encoded connector-manager info.
-   *
-   * @param string The encoded info.
-   * @return The decoded info.
-   */
-  public static ConnMgrInfo valueOf(String string) {
-    return ConfigSingleton.getGson().fromJson(string, ConnMgrInfo.class);
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(new TypeToken<ImmutableSet<Entry>>() {}.getType(),
-        TypeAdapters.immutableSet());
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/CredentialGroup.java b/src/com/google/enterprise/secmgr/config/CredentialGroup.java
deleted file mode 100644
index 200d447..0000000
--- a/src/com/google/enterprise/secmgr/config/CredentialGroup.java
+++ /dev/null
@@ -1,320 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-
-import java.util.Collection;
-import java.util.List;
-
-import javax.annotation.concurrent.Immutable;
-import javax.annotation.concurrent.NotThreadSafe;
-
-/**
- * A "credential group" is a set of authentication mechanisms that are defined
- * to share a common username and password.
- */
-@Immutable
-public class CredentialGroup {
-
-  public static final String DEFAULT_NAME = "Default";
-
-  private final String name;
-  private final AuthnAuthority authority;
-  private final String displayName;
-  private final boolean requiresUsername;   // Not satisfied until a username is known.
-  private final boolean requiresPassword;   // Not satisfied until a password is known.
-  private final boolean isOptional;         // Can be satisfied given blank username & password.
-  private final ImmutableList<AuthnMechanism> mechanisms;
-
-  private CredentialGroup(String name, String displayName, boolean requiresUsername,
-      boolean requiresPassword, boolean isOptional, List<AuthnMechanism> mechanisms) {
-    Preconditions.checkArgument(name != null && AuthnMechanism.isValidConfigName(name),
-        "Invalid credential-group name: %s", name);
-    this.name = name;
-    authority = AuthnAuthority.make(name);
-    this.displayName = (displayName != null) ? displayName : name;
-    this.requiresUsername = requiresUsername;
-    this.requiresPassword = requiresPassword;
-    this.isOptional = isOptional;
-    this.mechanisms = ImmutableList.copyOf(mechanisms);
-  }
-
-  /**
-   * Get a credential-group builder.
-   *
-   * @param name The name of the group; used in ACLs.
-   * @param displayName The name of the group as presented to end users.
-   * @param requiresUsername Does the group require a verified username?
-   * @param requiresPassword Does the group require a verified password?
-   * @param isOptional False if the credentials for this group must be supplied.
-   * @return A credential-group builder with given initial settings and no mechanisms.
-   */
-  public static Builder builder(String name, String displayName, boolean requiresUsername,
-        boolean requiresPassword, boolean isOptional) {
-    return new Builder(name, displayName, requiresUsername, requiresPassword, isOptional);
-  }
-
-  /**
-   * Get a credential-group builder.
-   *
-   * @param group A credential group to get the initial settings from.
-   * @return A credential-group builder initialized with the given credential group.
-   */
-  public static Builder builder(CredentialGroup group) {
-    Builder newBuilder = new Builder(group.getName(), group.getDisplayName(),
-        group.getRequiresUsername(), group.getRequiresPassword(), group.getIsOptional());
-    newBuilder.addMechanisms(group.getMechanisms());
-    return newBuilder;
-  }
-
-  /**
-   * Get a credential-group builder.
-   *
-   * @return A credential-group builder with default initial settings and no mechanisms.
-   */
-  public static Builder builder() {
-    return builder(DEFAULT_NAME, DEFAULT_NAME, true, false, false);
-  }
-
-  /**
-   * A builder factor for credential-group instances.
-   */
-  @NotThreadSafe
-  public static final class Builder {
-
-    private String name;
-    private String displayName;
-    private boolean requiresUsername;
-    private boolean requiresPassword;
-    private boolean isOptional;
-    private List<AuthnMechanism> mechanisms;
-
-    private Builder(String name, String displayName, boolean requiresUsername,
-        boolean requiresPassword, boolean isOptional) {
-      this.name = name;
-      this.displayName = displayName;
-      this.requiresUsername = requiresUsername;
-      this.requiresPassword = requiresPassword;
-      this.isOptional = isOptional;
-      this.mechanisms = Lists.newArrayList();
-    }
-
-    public String getName() {
-      return name;
-    }
-
-    public Builder setName(String name) {
-      this.name = name;
-      return this;
-    }
-
-    public Builder setDisplayName(String displayName) {
-      this.displayName = displayName;
-      return this;
-    }
-
-    public Builder setRequiresUsername(boolean requiresUsername) {
-      this.requiresUsername = requiresUsername;
-      return this;
-    }
-
-    public Builder setRequiresPassword(boolean requiresPassword) {
-      this.requiresPassword = requiresPassword;
-      return this;
-    }
-
-    public Builder setIsOptional(boolean isOptional) {
-      this.isOptional = isOptional;
-      return this;
-    }
-
-    public List<AuthnMechanism> getMechanisms() {
-      return mechanisms;
-    }
-
-    public Builder addMechanism(AuthnMechanism mechanism) {
-      mechanisms.add(mechanism);
-      return this;
-    }
-
-    public Builder addMechanism(int index, AuthnMechanism mechanism) {
-      mechanisms.add(index, mechanism);
-      return this;
-    }
-
-    public Builder addMechanisms(Collection<AuthnMechanism> mechanisms) {
-      this.mechanisms.addAll(mechanisms);
-      return this;
-    }
-
-    public AuthnMechanism findMechanism(String name) {
-      for (AuthnMechanism mechanism : mechanisms) {
-        if (name.equalsIgnoreCase(mechanism.getName())) {
-          return mechanism;
-        }
-      }
-      return null;
-    }
-
-    public Builder replaceMechanism(AuthnMechanism mechanism) {
-      AuthnMechanism other = findMechanism(mechanism.getName());
-      Preconditions.checkArgument(other != null,
-          "No existing mechanism with this name: %s", mechanism.getName());
-      mechanisms.remove(other);
-      mechanisms.add(mechanism);
-      return this;
-    }
-
-    public CredentialGroup build() {
-      return new CredentialGroup(name, displayName, requiresUsername, requiresPassword, isOptional,
-          mechanisms);
-    }
-  }
-
-  public String getName() {
-    return name;
-  }
-
-  public AuthnAuthority getAuthority() {
-    return authority;
-  }
-
-  public String getDisplayName() {
-    return displayName;
-  }
-
-  public ImmutableList<AuthnMechanism> getMechanisms() {
-    return mechanisms;
-  }
-
-  public boolean hasMechanismOfType(Class<? extends AuthnMechanism> type) {
-    for (AuthnMechanism mech : mechanisms) {
-      if (type.isInstance(mech)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  public boolean getRequiresUsername() {
-    return requiresUsername;
-  }
-
-  public boolean getRequiresPassword() {
-    return requiresPassword;
-  }
-
-  public boolean getIsOptional() {
-    return isOptional;
-  }
-
-  @Override
-  public String toString() {
-    return ConfigSingleton.getGson().toJson(this);
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof CredentialGroup)) { return false; }
-    CredentialGroup other = (CredentialGroup) object;
-    return Objects.equal(name, other.name)
-        && Objects.equal(displayName, other.displayName)
-        && Objects.equal(requiresUsername, other.requiresUsername)
-        && Objects.equal(requiresPassword, other.requiresPassword)
-        && Objects.equal(isOptional, other.isOptional)
-        && Objects.equal(mechanisms, other.mechanisms);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hashCode(name, displayName, requiresUsername, requiresPassword, isOptional,
-        mechanisms);
-  }
-
-  public boolean isDefault() {
-    return DEFAULT_NAME.equalsIgnoreCase(name);
-  }
-
-  public boolean canUseUlfCredentials() {
-    for (AuthnMechanism mech : mechanisms) {
-      if (mech.canUseUlfCredentials()) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  public static final Predicate<CredentialGroup> DEFAULT_PREDICATE =
-      new Predicate<CredentialGroup>() {
-        public boolean apply(CredentialGroup credentialGroup) {
-          return credentialGroup.isDefault();
-        }
-      };
-
-  public static final Function<Builder, CredentialGroup> BUILD_FUNCTION =
-      new Function<Builder, CredentialGroup>() {
-        public CredentialGroup apply(Builder builder) {
-          return builder.build();
-        }
-      };
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(CredentialGroup.class,
-        ProxyTypeAdapter.make(CredentialGroup.class, LocalProxy.class));
-    builder.registerTypeAdapter(new TypeToken<ImmutableList<AuthnMechanism>>() {}.getType(),
-        TypeAdapters.immutableList());
-  }
-
-  private static final class LocalProxy implements TypeProxy<CredentialGroup> {
-    String name;
-    String displayName;
-    boolean requiresUsername;
-    boolean requiresPassword;
-    boolean isOptional;
-    ImmutableList<AuthnMechanism> mechanisms;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(CredentialGroup credentialGroup) {
-      name = credentialGroup.name;
-      displayName = credentialGroup.displayName;
-      requiresUsername = credentialGroup.requiresUsername;
-      requiresPassword = credentialGroup.requiresPassword;
-      isOptional = credentialGroup.isOptional;
-      mechanisms = credentialGroup.mechanisms;
-    }
-
-    @Override
-    public CredentialGroup build() {
-      return new CredentialGroup(name, displayName, requiresUsername, requiresPassword, isOptional,
-          mechanisms);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/CredentialTransform.java b/src/com/google/enterprise/secmgr/config/CredentialTransform.java
deleted file mode 100644
index 8e580ff..0000000
--- a/src/com/google/enterprise/secmgr/config/CredentialTransform.java
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.config;
-
-/**
- * A model of a particular credential transform implemented by a mechanism.
- * For example, a typical transform accepts some credentials as inputs and
- * verifies them, returning mutually-verified credentials.
- */
-public final class CredentialTransform {
-  private final CredentialTypeSet inputs;
-  private final CredentialTypeSet outputs;
-
-  private CredentialTransform(CredentialTypeSet inputs, CredentialTypeSet outputs) {
-    this.inputs = inputs;
-    this.outputs = outputs;
-  }
-
-  /**
-   * Make a credential transform.
-   *
-   * @param inputs The inputs to the transform.
-   * @param outputs The outputs from the transform.
-   * @return A transform with the given inputs and outputs.
-   */
-  public static CredentialTransform make(CredentialTypeSet inputs, CredentialTypeSet outputs) {
-    return new CredentialTransform(inputs, outputs);
-  }
-
-  /**
-   * @return The inputs to this transform.
-   */
-  public CredentialTypeSet getInputs() {
-    return inputs;
-  }
-
-  /**
-   * @return The outputs from this transform.
-   */
-  public CredentialTypeSet getOutputs() {
-    return outputs;
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/CredentialTypeName.java b/src/com/google/enterprise/secmgr/config/CredentialTypeName.java
deleted file mode 100644
index 6ae5146..0000000
--- a/src/com/google/enterprise/secmgr/config/CredentialTypeName.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.config;
-
-/**
- * A set of tokens identifying the possible credential types.  Used by modeling
- * in preference to the classes that implement these types.
- */
-public enum CredentialTypeName {
-  PRINCIPAL, PASSWORD, ALIASES, GROUPS, COOKIES, KERBEROS_TICKET, X509_CERTIFICATE;
-}
diff --git a/src/com/google/enterprise/secmgr/config/CredentialTypeSet.java b/src/com/google/enterprise/secmgr/config/CredentialTypeSet.java
deleted file mode 100644
index 3a10c5a..0000000
--- a/src/com/google/enterprise/secmgr/config/CredentialTypeSet.java
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-
-import java.util.Set;
-
-/**
- * A set of credential types, used as an input to or output from a credential
- * transform.
- */
-public class CredentialTypeSet {
-  private final boolean areVerified;
-  private final ImmutableSet<CredentialTypeName> elements;
-
-  private CredentialTypeSet(boolean areVerified, ImmutableSet<CredentialTypeName> elements) {
-    this.areVerified = areVerified;
-    this.elements = elements;
-  }
-
-  /**
-   * Make a credential-type set.
-   *
-   * @param areVerified True if the represented credentials are verified.
-   * @param elements The credential types that are the elements of this set.
-   * @return A credential-type set with those elements.
-   */
-  public static CredentialTypeSet make(boolean areVerified, Iterable<CredentialTypeName> elements) {
-    return new CredentialTypeSet(areVerified, ImmutableSet.copyOf(elements));
-  }
-
-  /**
-   * @return True if the credentials are mutually verified.
-   */
-  public boolean getAreVerified() {
-    return areVerified;
-  }
-
-  /**
-   * @return An immutable set of the credential types that are the elements of
-   * this set.
-   */
-  public Set<CredentialTypeName> getElements() {
-    return elements;
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof CredentialTypeSet)) { return false; }
-    CredentialTypeSet other = (CredentialTypeSet) object;
-    return Objects.equal(getAreVerified(), other.getAreVerified())
-        && Objects.equal(getElements(), other.getElements());
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hashCode(getAreVerified(), getElements());
-  }
-
-  public static final CredentialTypeSet NONE =
-      make(false, ImmutableList.<CredentialTypeName>of());
-
-  public static final CredentialTypeSet COOKIES =
-      make(false, ImmutableList.of(CredentialTypeName.COOKIES));
-
-  public static final CredentialTypeSet PRINCIPAL_AND_PASSWORD =
-      make(false, ImmutableList.of(CredentialTypeName.PRINCIPAL, CredentialTypeName.PASSWORD));
-
-  public static final CredentialTypeSet VERIFIED_PRINCIPAL_AND_PASSWORD =
-      make(true, ImmutableList.of(CredentialTypeName.PRINCIPAL, CredentialTypeName.PASSWORD));
-
-  public static final CredentialTypeSet VERIFIED_PRINCIPAL_PASSWORD_AND_GROUPS =
-      make(true, ImmutableList.of(CredentialTypeName.PRINCIPAL, CredentialTypeName.PASSWORD,
-              CredentialTypeName.GROUPS));
-
-  public static final CredentialTypeSet VERIFIED_PRINCIPAL =
-      make(true, ImmutableList.of(CredentialTypeName.PRINCIPAL));
-
-  public static final CredentialTypeSet VERIFIED_ALIASES =
-      make(true, ImmutableList.of(CredentialTypeName.ALIASES));
-
-  public static final CredentialTypeSet VERIFIED_GROUPS =
-      make(true, ImmutableList.of(CredentialTypeName.GROUPS));
-}
diff --git a/src/com/google/enterprise/secmgr/config/FlexAuthorizer.java b/src/com/google/enterprise/secmgr/config/FlexAuthorizer.java
deleted file mode 100644
index 0597a0c..0000000
--- a/src/com/google/enterprise/secmgr/config/FlexAuthorizer.java
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.config;
-
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Interface for Flexible Authorization.
- *
- * This class provides accessors and mutators for the Authz Routing Table and
- * the Authz Rules Table.  Each entry in the routing table is uniquely defined
- * by a UUID.  Each rule in the rule table is uniquely defined by its display
- * name.
- *
- * @author meghna@google.com (Meghna Dhar)
- */
-public interface FlexAuthorizer {
-
-  /**
-   * Add an entry to the routing table.
-   *
-   * @param order The priority order for the entry; the entry will
-   *     be stored at that position, and all subsequent entries have their order
-   *     increased by one.
-   * @param entry The entry to be added.
-   * @throws IllegalArgumentException if the new entry refers to a rule that's
-   *     not in the rule table, or if the order is less than zero or greater
-   *     than the number of entries in the routing table.
-   */
-  public void addToRoutingTable(int order, FlexAuthzRoutingTableEntry entry);
-
-  /**
-   * Add an entry at the end of the routing table.
-   *
-   * @param entry The entry to be added.
-   * @throws IllegalArgumentException if the new entry refers to a rule that's
-   *     not in the rule table.
-   */
-  public void addToRoutingTable(FlexAuthzRoutingTableEntry entry);
-
-  /**
-   * Delete an entry from the routing table.
-   *
-   * @param uuid The UUID of the entry to delete.
-   * @throws IllegalArgumentException if there's no entry in the table with that UUID.
-   */
-  public void deleteFromRoutingTable(UUID uuid);
-
-  /**
-   * Update an entry in the routing table.
-   *
-   * @param order The priority order for the entry; the entry will
-   *     be stored at that position, and all subsequent entries have their order
-   *     increased by one.
-   * @param entry The new entry; must have the same UUID as an existing entry.
-   * @throws IllegalArgumentException if the entry refers to a rule that's not
-   *     in the rule table, or if the entry's UUID doesn't match an existing
-   *     entry.
-   */
-  public void updateRoutingTable(int order, FlexAuthzRoutingTableEntry entry);
-
-  /**
-   * Given a UUID, get the corresponding entry from the routing table.
-   *
-   * @param uuid The UUID to search for.
-   * @return The corresponding entry, or null if there's none.
-   */
-  public FlexAuthzRoutingTableEntry getFromRoutingTable(UUID uuid);
-
-  /**
-   * Given a UUID, get the priority order of the corresponding entry in the routing table.
-   *
-   * @param uuid The UUID to search for.
-   * @return The priority order of the corresponding entry, or -1 if there's none.
-   */
-  public int getRoutingPriorityOrder(UUID uuid);
-
-  /**
-   * Get all the entries in the routing table, in priority order.
-   *
-   * @return An immutable list of the routing-table entries.
-   */
-  public List<FlexAuthzRoutingTableEntry> getAllRoutingTable();
-
-  /**
-   * @return The number of entries in the routing table.
-   */
-  public int getRoutingTableSize();
-
-  /**
-   * Add a new rule to the rule table.
-   *
-   * @param entry The rule to be added.
-   * @throws IllegalArgumentException if there's already a rule of that name in the table.
-   */
-  public void addToRulesTable(FlexAuthzRule entry);
-
-  /**
-   * Delete a rule from the rule table.
-   *
-   * @param displayName The name of the rule to delete.
-   * @throws IllegalStateException if the rule is referred to by a routing-table
-   *     entry, or if there's no rule of that name in the rule table.
-   */
-  public void deleteFromRulesTable(String displayName);
-
-  /**
-   * Update a rule in the rule table.  Also updates all the routing-table
-   * entries that refer to the rule being replaced.
-   *
-   * @param entry The replacement rule.
-   * @throws IllegalArgumentException if there's no rule of that name in the table.
-   */
-  public void updateRulesTable(FlexAuthzRule entry);
-
-  /**
-   * Given a name, get the matching rule from the rule table.
-   *
-   * @param displayName The name to search for.
-   * @return The rule with that name, or null if there's none.
-   */
-  public FlexAuthzRule getFromRulesTable(String displayName);
-
-  /**
-   * Get all the rules in the rule table.
-   *
-   * @return An immutable list of the rules in the table.
-   */
-  public List<FlexAuthzRule> getAllRulesTable();
-
-  /**
-   * Clear the tables.
-   */
-  public void clearTables();
-}
diff --git a/src/com/google/enterprise/secmgr/config/FlexAuthorizerImpl.java b/src/com/google/enterprise/secmgr/config/FlexAuthorizerImpl.java
deleted file mode 100644
index f0414a2..0000000
--- a/src/com/google/enterprise/secmgr/config/FlexAuthorizerImpl.java
+++ /dev/null
@@ -1,296 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-import com.google.inject.Inject;
-
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-/**
- * A basic implementation of FlexAuthorizer.  This provides the primary logic
- * for everything except serialization.  The routing table is stored as a list
- * and the priority order is the ordering in the list.  Each row has a unique
- * identifier.  The rule table is stored as a map and the key is the display
- * name of the row.
- *
- * @author meghna@google.com (Meghna Dhar)
- */
-public final class FlexAuthorizerImpl implements FlexAuthorizer {
-
-  private static final String ROOT_URL_PATTERN = "/";
-
-  private final Map<String, FlexAuthzRule> ruleTable;
-  private final List<FlexAuthzRoutingTableEntry> routingTable;
-
-  @Inject
-  private FlexAuthorizerImpl() {
-    ruleTable = Maps.newHashMap();
-    routingTable = Lists.newArrayList();
-  }
-
-  @VisibleForTesting
-  FlexAuthorizerImpl(Map<String, FlexAuthzRule> ruleTable,
-      List<FlexAuthzRoutingTableEntry> routingTable) {
-    this.ruleTable = ruleTable;
-    this.routingTable = routingTable;
-  }
-
-  @Override
-  public void addToRoutingTable(int order, FlexAuthzRoutingTableEntry entry) {
-    checkPriorityOrder(order, routingTable.size());
-    checkForMatchingRule(entry.getAuthzRule());
-    routingTable.add(order, entry);
-  }
-
-  @Override
-  public void addToRoutingTable(FlexAuthzRoutingTableEntry entry) {
-    checkForMatchingRule(entry.getAuthzRule());
-    routingTable.add(entry);
-  }
-
-  @Override
-  public void addToRulesTable(FlexAuthzRule rule) {
-    String name = rule.getRowDisplayName();
-    Preconditions.checkArgument(ruleTable.get(name) == null,
-        "Rule already exists: %s", name);
-    ruleTable.put(name, rule);
-  }
-
-  @Override
-  public void clearTables() {
-    routingTable.clear();
-    ruleTable.clear();
-  }
-
-  @Override
-  public void deleteFromRoutingTable(UUID uuid) {
-    Preconditions.checkNotNull(uuid);
-    int index = getRoutingPriorityOrder(uuid);
-    Preconditions.checkArgument(index >= 0, "Entry not found in routing table: %s", uuid);
-    routingTable.remove(index);
-  }
-
-  @Override
-  public void deleteFromRulesTable(String name) {
-    Preconditions.checkNotNull(name);
-    FlexAuthzRule rule = ruleTable.get(name);
-    Preconditions.checkArgument(rule != null, "Rule isn't in table: %s", name);
-    for (FlexAuthzRoutingTableEntry entry : routingTable) {
-      Preconditions.checkState(entry.getAuthzRule() != rule,
-          "Rule '%s' is referred to by one or more routing-table entries: %s",
-          name, entry.getUniqueRowId().toString());
-    }
-    ruleTable.remove(name);
-  }
-
-  @Override
-  public List<FlexAuthzRoutingTableEntry> getAllRoutingTable() {
-    return ImmutableList.copyOf(routingTable);
-  }
-
-  @Override
-  public List<FlexAuthzRule> getAllRulesTable() {
-    return ImmutableList.copyOf(ruleTable.values());
-  }
-
-  @Override
-  public int getRoutingTableSize() {
-    return routingTable.size();
-  }
-
-  @Override
-  public FlexAuthzRoutingTableEntry getFromRoutingTable(UUID uuid) {
-    Preconditions.checkNotNull(uuid);
-    for (FlexAuthzRoutingTableEntry entry : routingTable) {
-      if (uuid.equals(entry.getUniqueRowId())) {
-        return entry;
-      }
-    }
-    return null;
-  }
-
-  @Override
-  public FlexAuthzRule getFromRulesTable(String name) {
-    Preconditions.checkNotNull(name);
-    return ruleTable.get(name);
-  }
-
-  @Override
-  public void updateRoutingTable(int order, FlexAuthzRoutingTableEntry entry) {
-    checkPriorityOrder(order, routingTable.size() - 1);
-    checkForMatchingRule(entry.getAuthzRule());
-    UUID uuid = entry.getUniqueRowId();
-    int oldIndex = getRoutingPriorityOrder(uuid);
-    Preconditions.checkArgument(oldIndex >= 0, "Entry not found in routing table: %s", uuid);
-    // oldIndex is valid in table prior to change; order is where we want the
-    // entry to be after the change.  So do the delete first, then the insert.
-    routingTable.remove(oldIndex);
-    routingTable.add(order, entry);
-  }
-
-  @Override
-  public void updateRulesTable(FlexAuthzRule rule) {
-    String name = rule.getRowDisplayName();
-    FlexAuthzRule oldRule = ruleTable.get(name);
-    Preconditions.checkArgument(oldRule != null, "Rule not in table: %s", name);
-    ruleTable.put(name, rule);
-    // Now update the routing table, replacing the old rule with the new.
-    for (int i = 0; i < routingTable.size(); i += 1) {
-      FlexAuthzRoutingTableEntry entry = routingTable.get(i);
-      if (entry.getAuthzRule() == oldRule) {
-        routingTable.set(i,
-            new FlexAuthzRoutingTableEntry(
-                entry.getUrlPattern(),
-                rule,
-                entry.getUniqueRowId()));
-      }
-    }
-  }
-
-  public int getRoutingPriorityOrder(UUID uuid) {
-    Preconditions.checkNotNull(uuid);
-    int index = 0;
-    for (FlexAuthzRoutingTableEntry entry : routingTable) {
-      if (entry.getUniqueRowId().equals(uuid)) {
-        return index;
-      }
-      index++;
-    }
-    return -1;
-  }
-
-  private void checkPriorityOrder(int order, int limit) {
-    Preconditions.checkArgument(order >= 0 && order <= limit,
-        "Priority order not in valid range: %d", order);
-  }
-
-  private void checkForMatchingRule(FlexAuthzRule rule) {
-    String ruleName = rule.getRowDisplayName();
-    Preconditions.checkArgument(ruleTable.get(ruleName) == rule,
-        "Rule in table doesn't match: %s", ruleName);
-  }
-
-  @Override
-  public String toString() {
-    return ConfigSingleton.getGson().toJson(this);
-  }
-
-  @Override
-  public synchronized boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof FlexAuthorizerImpl)) { return false; }
-    FlexAuthorizerImpl other = (FlexAuthorizerImpl) object;
-    return Objects.equal(getAllRulesTable(), other.getAllRulesTable())
-        && Objects.equal(getAllRoutingTable(), other.getAllRoutingTable());
-  }
-
-  @Override
-  public synchronized int hashCode() {
-    return Objects.hashCode(getAllRulesTable(), getAllRoutingTable());
-  }
-
-  public static FlexAuthorizer makeDefault() {
-    return makeDefault(null, false);
-  }
-
-  public static FlexAuthorizer makeDefault(String authzServiceUrl, boolean samlUseBatchedRequests) {
-    FlexAuthorizer flexAuthorizer = new FlexAuthorizerImpl();
-    int index = 0;
-    makeDefaultRule(flexAuthorizer, index++, ROOT_URL_PATTERN,
-        AuthzMechanism.CACHE,
-        FlexAuthzRule.EMPTY_AUTHN_ID);
-    makeDefaultRule(flexAuthorizer, index++, ROOT_URL_PATTERN,
-        AuthzMechanism.POLICY,
-        FlexAuthzRule.LEGACY_AUTHN_ID);
-    if (!Strings.isNullOrEmpty(authzServiceUrl)) {
-      makeDefaultRule(flexAuthorizer, index++, ROOT_URL_PATTERN,
-          AuthzMechanism.SAML,
-          FlexAuthzRule.LEGACY_AUTHN_ID,
-          ImmutableMap.of(
-              FlexAuthzRule.ParamName.SAML_ENTITY_ID, FlexAuthzRule.LEGACY_SAML_ENTITY_ID,
-              FlexAuthzRule.ParamName.SAML_USE_BATCHED_REQUESTS,
-              Boolean.toString(samlUseBatchedRequests)));
-    }
-    makeDefaultRule(flexAuthorizer, index++, FlexAuthzRule.LEGACY_CONNECTOR_URL_PATTERN,
-        AuthzMechanism.CONNECTOR,
-        FlexAuthzRule.LEGACY_AUTHN_ID,
-        ImmutableMap.of(
-            FlexAuthzRule.ParamName.CONNECTOR_NAME, FlexAuthzRule.EMPTY_CONNECTOR_NAME));
-    makeDefaultRule(flexAuthorizer, index++, ROOT_URL_PATTERN,
-        AuthzMechanism.HEADREQUEST,
-        FlexAuthzRule.LEGACY_AUTHN_ID);
-    return flexAuthorizer;
-  }
-
-  private static void makeDefaultRule(FlexAuthorizer flexAuthorizer, int index, String urlPattern,
-      AuthzMechanism authzMechType, String authnId,
-      Map<FlexAuthzRule.ParamName, String> mechSpecificParams) {
-    FlexAuthzRule rule
-        = new FlexAuthzRule(authnId, authzMechType, mechSpecificParams, String.valueOf(index),
-            FlexAuthzRule.NO_TIME_LIMIT);
-    flexAuthorizer.addToRulesTable(rule);
-    flexAuthorizer.addToRoutingTable(new FlexAuthzRoutingTableEntry(urlPattern, rule));
-  }
-
-  private static void makeDefaultRule(FlexAuthorizer flexAuthorizer, int index, String urlPattern,
-      AuthzMechanism authzMechType, String authnId) {
-    FlexAuthzRule rule
-        = new FlexAuthzRule(authnId, authzMechType, String.valueOf(index),
-            FlexAuthzRule.NO_TIME_LIMIT);
-    flexAuthorizer.addToRulesTable(rule);
-    flexAuthorizer.addToRoutingTable(new FlexAuthzRoutingTableEntry(urlPattern, rule));
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(FlexAuthorizer.class,
-        ProxyTypeAdapter.make(FlexAuthorizer.class, LocalProxy.class));
-  }
-
-  private static final class LocalProxy implements TypeProxy<FlexAuthorizer> {
-    List<FlexAuthzRoutingTableEntry> entries;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(FlexAuthorizer flexAuthorizer) {
-      entries = flexAuthorizer.getAllRoutingTable();
-    }
-
-    @Override
-    public FlexAuthorizer build() {
-      Map<String, FlexAuthzRule> ruleTable = Maps.newHashMap();
-      for (FlexAuthzRoutingTableEntry entry : entries) {
-        FlexAuthzRule rule = entry.getAuthzRule();
-        ruleTable.put(rule.getRowDisplayName(), rule);
-      }
-      return new FlexAuthorizerImpl(ruleTable, entries);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/FlexAuthzRoutingTableEntry.java b/src/com/google/enterprise/secmgr/config/FlexAuthzRoutingTableEntry.java
deleted file mode 100644
index d41700d..0000000
--- a/src/com/google/enterprise/secmgr/config/FlexAuthzRoutingTableEntry.java
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.labs.matcher.ParsedUrlPattern;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-
-import java.util.UUID;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
-/**
- * Implementation of the Flexible Authorization Routing Table Row.
- *
- * Each row in the routing table contains
- * Url Pattern - a string which specifies either a single document via a
- * specific URL or a set of documents that share the same pattern,
- * pointer to the Authz Rule and a unique row identifier.
- *
- * @author meghna@google.com (Meghna Dhar)
- *
- */
-public class FlexAuthzRoutingTableEntry {
-  private final String urlPattern;
-  private final FlexAuthzRule authzRule;
-  private final UUID uniqueRowId;
-
-  public static boolean isValidPattern(String patternStr) {
-    if (patternStr.isEmpty()) {
-      return false;
-    }
-    try {
-      ParsedUrlPattern p = new ParsedUrlPattern(patternStr);
-    } catch (IllegalArgumentException e) {
-      return false;
-    }
-
-    String regexpProtocols[] = new String[] { "regexp:", "regexpIgnoreCase:", "regexpCase:" };
-    for (String regexpProtocol : regexpProtocols) {
-      if (patternStr.startsWith(regexpProtocol)) {
-        try {
-          Pattern.compile(patternStr.substring(regexpProtocol.length()));
-        } catch (PatternSyntaxException e) {
-          return false;
-        }
-      }
-    }
-
-    // TODO(???): Introduce addtional validation as ParsedUrlPattern is lax.
-    /* GSA rules on valid URL patterns:
-       http://code.google.com/apis/searchappliance/documentation/50/help_gsa/z01apprules.html */
-
-    return true;
-  }
-
-  public FlexAuthzRoutingTableEntry(String urlPattern, FlexAuthzRule authzRule) {
-    this(urlPattern, authzRule, UUID.randomUUID());
-  }
-
-  public FlexAuthzRoutingTableEntry(String urlPattern, FlexAuthzRule authzRule,
-      UUID uuid) {
-    if (!isValidPattern(urlPattern)) {
-      throw new IllegalArgumentException("invalid pattern: " + urlPattern);
-    }
-    this.urlPattern = urlPattern;
-    this.authzRule = authzRule;
-    this.uniqueRowId = uuid;
-  }
-
-  public String getUrlPattern() {
-    return urlPattern;
-  }
-
-  public FlexAuthzRule getAuthzRule() {
-    return authzRule;
-  }
-
-  public UUID getUniqueRowId(){
-    return uniqueRowId;
-  }
-
-  @Override
-  public String toString() {
-    return ConfigSingleton.getGson().toJson(this);
-  }
-
-  /**
-   * only intended to be used for testing
-   * Since each time the default config is loaded, there will be a new
-   * uniqueRowId generated, we do not include the uniqueRowId in the
-   * equals method
-   */
-  @Override
-  public synchronized boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof FlexAuthzRoutingTableEntry)) { return false; }
-    FlexAuthzRoutingTableEntry other = (FlexAuthzRoutingTableEntry) object;
-    return Objects.equal(getUrlPattern(), other.getUrlPattern())
-        && Objects.equal(getAuthzRule(), other.getAuthzRule());
-  }
-
-  @Override
-  public synchronized int hashCode() {
-      return Objects.hashCode(getUrlPattern(), getAuthzRule(), getUniqueRowId());
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(FlexAuthzRoutingTableEntry.class,
-        ProxyTypeAdapter.make(FlexAuthzRoutingTableEntry.class, LocalProxy.class));
-  }
-
-  private static final class LocalProxy implements TypeProxy<FlexAuthzRoutingTableEntry> {
-    String urlPattern;
-    FlexAuthzRule authzRule;
-    UUID uniqueRowId;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(FlexAuthzRoutingTableEntry entry) {
-      urlPattern = entry.getUrlPattern();
-      authzRule = entry.getAuthzRule();
-      uniqueRowId = entry.getUniqueRowId();
-    }
-
-    @Override
-    public FlexAuthzRoutingTableEntry build() {
-      return new FlexAuthzRoutingTableEntry(urlPattern, authzRule, uniqueRowId);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/FlexAuthzRule.java b/src/com/google/enterprise/secmgr/config/FlexAuthzRule.java
deleted file mode 100644
index c3ae80d..0000000
--- a/src/com/google/enterprise/secmgr/config/FlexAuthzRule.java
+++ /dev/null
@@ -1,283 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * Implementation of the Flexible Authorization Rule.
- *
- * @author meghna@google.com (Meghna Dhar)
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public class FlexAuthzRule {
-
-  /**
-   * Mechanism-specific parameter names.
-   */
-  public static enum ParamName {
-    /**
-     * Indicates a connector-instance name.  This is a required string-valued
-     * parameter.
-     */
-    CONNECTOR_NAME,
-    /**
-     * Indicates the entity ID of a SAML PDP.  This is a required string-valued
-     * parameter.
-     */
-    SAML_ENTITY_ID,
-    /**
-     * Indicates whether to use the "multi-request" authz protocol.  This is a
-     * required boolean-valued parameter.
-     */
-    SAML_USE_BATCHED_REQUESTS,
-  }
-
-  /**
-   * The empty authentication ID, for use with mechanisms like
-   * {@link AuthzMechanism#CACHE} and {@link AuthzMechanism#POLICY}.
-   */
-  public static final String EMPTY_AUTHN_ID = "";
-
-  /**
-   * The legacy authentication ID, for configuration migration.
-   */
-  public static final String LEGACY_AUTHN_ID = "Default";
-
-  /**
-   * The empty connector name, for use with {@link #LEGACY_CONNECTOR_URL_PATTERN}.
-   */
-  public static final String EMPTY_CONNECTOR_NAME = "";
-
-  /**
-   * The legacy connector URL pattern {@code "^googleconnector://"}.
-   */
-  public static final String LEGACY_CONNECTOR_URL_PATTERN = "^googleconnector://";
-
-  /**
-   * The SAML entity ID to use for legacy SAML clients.
-   */
-  public static final String LEGACY_SAML_ENTITY_ID = "http://example.com/legacy-saml-id";
-
-  /**
-   * Timeout value that indicates this rule has no specific time limit.
-   */
-  public static final int NO_TIME_LIMIT = -1;
-
-  private static final ImmutableList<AuthzMechanism> AUTHZ_MECHANISMS =
-      ImmutableList.copyOf(EnumSet.allOf(AuthzMechanism.class));
-
-  @Nonnull private final String authnId;
-  @Nonnull private final AuthzMechanism authzMechType;
-  @Nonnull private final ImmutableMap<ParamName, String> mechSpecificParams;
-  @Nonnull private final String displayName;
-  private final int timeout;
-
-  /**
-   * Constructor for flex authz rules.
-   *
-   * @param authnId The name of a credential group to use for authorization, or
-   *     an empty string to use the "primary verified identity".
-   * @param authzMechType The authorization mechanism type, for example policy
-   *     ACLs, head requests, connector authorization, SAML, etc.
-   * @param mechSpecificParams A map of parameters that are specific to the
-   *     mechanism type.  A null value is equivalent to an empty map.
-   * @param displayName The display name for this rule's row, which can be used
-   *     as a reference in the routing table.
-   * @param timeout  The timeout for this rule, in milliseconds.
-   */
-  public FlexAuthzRule(String authnId, AuthzMechanism authzMechType,
-      Map<ParamName, String> mechSpecificParams, String displayName, int timeout) {
-    Preconditions.checkNotNull(authnId);
-    Preconditions.checkNotNull(authzMechType);
-    Preconditions.checkNotNull(displayName);
-    this.authnId = authnId;
-    this.authzMechType = authzMechType;
-    if (mechSpecificParams != null) {
-      this.mechSpecificParams = ImmutableMap.copyOf(mechSpecificParams);
-    } else {
-      this.mechSpecificParams = ImmutableMap.of();
-    }
-    this.displayName = displayName;
-    this.timeout = timeout;
-  }
-
-  /**
-   * A constructor for flex authz rules with no mechanism-specific parameters.
-   */
-  public FlexAuthzRule(String authnId, AuthzMechanism mechType, String displayName, int timeout) {
-    this(authnId, mechType, null, displayName, timeout);
-  }
-
-  /** A dummy rule to use when only the timeout matters. */
-  public static final FlexAuthzRule UNCONSTRAINED
-      = new FlexAuthzRule(EMPTY_AUTHN_ID, AuthzMechanism.DENY, "", NO_TIME_LIMIT);
-
-  /** A dummy rule to use for fast authorization. */
-  public static final FlexAuthzRule FAST_AUTHORIZATION
-      = new FlexAuthzRule(EMPTY_AUTHN_ID, AuthzMechanism.DENY, "Fast Authorization", NO_TIME_LIMIT);
-
-  /**
-   * @return The authentication identity name for this rule: a credential-group
-   * name, or the empty string to use the "primary verified identity".
-   */
-  @Nonnull
-  public String getAuthnId() {
-    return authnId;
-  }
-
-  /**
-   * @return The authorization mechanism type for this rule.
-   */
-  @Nonnull
-  public AuthzMechanism getAuthzMechType() {
-    return authzMechType;
-  }
-
-  /**
-   * @return A collection of the available mechanism types.
-   */
-  @Nonnull
-  public static Collection<AuthzMechanism> getAuthzMechTypes() {
-    return AUTHZ_MECHANISMS;
-  }
-
-  /**
-   * @return An immutable copy of the mechanism-specific parameters.
-   */
-  @Nonnull
-  public Map<ParamName, String> getMechSpecificParams() {
-    return mechSpecificParams;
-  }
-
-  @Nonnull
-  public String requiredStringParam(ParamName name) {
-    String value = mechSpecificParams.get(name);
-    Preconditions.checkArgument(value != null);
-    return value;
-  }
-
-  @Nonnull
-  public boolean requiredBooleanParam(ParamName name) {
-    return Boolean.valueOf(requiredStringParam(name));
-  }
-
-  /**
-   * @return The display name for this rule's row.
-   */
-  @Nonnull
-  public String getRowDisplayName() {
-    return displayName;
-  }
-
-  /**
-   * @return The timeout for this rule, in milliseconds.
-   */
-  public int getTimeout() {
-    return timeout;
-  }
-
-  public boolean hasTimeout() {
-    return NO_TIME_LIMIT != timeout;
-  }
-
-  @Override
-  public String toString() {
-    return ConfigSingleton.getGson().toJson(this);
-  }
-
-  @Override
-  public synchronized boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof FlexAuthzRule)) { return false; }
-    FlexAuthzRule other = (FlexAuthzRule) object;
-    return Objects.equal(getAuthnId(), other.getAuthnId())
-        && Objects.equal(getAuthzMechType(), other.getAuthzMechType())
-        && Objects.equal(getMechSpecificParams(), other.getMechSpecificParams())
-        && Objects.equal(getRowDisplayName(), other.getRowDisplayName())
-        && Objects.equal(getTimeout(), other.getTimeout());
-  }
-
-  @Override
-  public synchronized int hashCode() {
-    return Objects.hashCode(getAuthnId(), getAuthzMechType(), getMechSpecificParams(),
-                            getRowDisplayName(), getTimeout());
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(FlexAuthzRule.class,
-        ProxyTypeAdapter.make(FlexAuthzRule.class, LocalProxy.class));
-  }
-
-  private static final class LocalProxy implements TypeProxy<FlexAuthzRule> {
-    String authnId;
-    AuthzMechanism authzMechType;
-    String connectorName;
-    String samlEntityId;
-    String samlUseBatchedRequests;
-    String displayName;
-    int timeout;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(FlexAuthzRule rule) {
-      authnId = rule.getAuthnId();
-      authzMechType = rule.getAuthzMechType();
-      connectorName = rule.getMechSpecificParams().get(ParamName.CONNECTOR_NAME);
-      samlEntityId = rule.getMechSpecificParams().get(ParamName.SAML_ENTITY_ID);
-      samlUseBatchedRequests
-          = rule.getMechSpecificParams().get(ParamName.SAML_USE_BATCHED_REQUESTS);
-      displayName = rule.getRowDisplayName();
-      timeout = rule.getTimeout();
-    }
-
-    @Override
-    public FlexAuthzRule build() {
-      Map<ParamName, String> mechSpecificParams = Maps.newHashMap();
-      if (connectorName != null) {
-        mechSpecificParams.put(ParamName.CONNECTOR_NAME, connectorName);
-      }
-      if (samlEntityId != null) {
-        mechSpecificParams.put(ParamName.SAML_ENTITY_ID, samlEntityId);
-      }
-      if (samlUseBatchedRequests != null) {
-        mechSpecificParams.put(ParamName.SAML_USE_BATCHED_REQUESTS, samlUseBatchedRequests);
-      }
-      if (mechSpecificParams.isEmpty()) {
-        mechSpecificParams = null;
-      }
-      return new FlexAuthzRule(authnId, authzMechType, mechSpecificParams, displayName, timeout);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/ParamName.java b/src/com/google/enterprise/secmgr/config/ParamName.java
deleted file mode 100644
index c131388..0000000
--- a/src/com/google/enterprise/secmgr/config/ParamName.java
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-
-import java.util.Iterator;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * Configuration parameter names, along with their types and default values.
- */
-@Immutable
-public enum ParamName {
-  ACL_GROUPS_FILENAME(String.class, "../../../../conf/acls/acl_groups.enterprise"),
-  ACL_URLS_FILENAME(String.class, "../../../../conf/acls/acl_urls.enterprise"),
-  CERTIFICATE_AUTHORITIES_FILENAME(String.class, "../../../../conf/certs/cacerts.jks"),
-  // whether to check the server certificate during serving time
-  CHECK_SERVER_CERTIFICATE(Boolean.class, Boolean.valueOf(true)),
-  CONNECTOR_MANAGER_INFO(ConnMgrInfo.class,
-      ConnMgrInfo.make(ImmutableSet.<ConnMgrInfo.Entry>of())),
-  DENY_RULES_FILENAME(String.class, "../../../../conf/deny_rules.enterprise"),
-  GLOBAL_BATCH_REQUEST_TIMEOUT(Float.class, Float.valueOf(2.5f)),
-  GLOBAL_SINGLE_REQUEST_TIMEOUT(Float.class, Float.valueOf(5.0f)),
-  LATE_BINDING_ACL(Boolean.class, Boolean.valueOf(false)),
-  SAML_METADATA_FILENAME(String.class, "../../../../conf/saml-metadata.xml"),
-  SERVER_CERTIFICATE_FILENAME(String.class, "../../../../conf/certs/server.jks"),
-  SIGNING_CERTIFICATE_FILENAME(String.class, "/etc/google/certs/server.crt"),
-  SIGNING_KEY_FILENAME(String.class, "/etc/google/certs/server.key"),
-  SLOW_HOST_EMBARGO_PERIOD(Integer.class, Integer.valueOf(600)),
-  SLOW_HOST_NUMBER_OF_TIMEOUTS(Integer.class, Integer.valueOf(100)),
-  SLOW_HOST_SAMPLE_PERIOD(Integer.class, Integer.valueOf(300)),
-  SLOW_HOST_TRACKER_ENABLED(Boolean.class, Boolean.valueOf(false)),
-  SLOW_HOST_TRACKER_SIZE(Integer.class, Integer.valueOf(100)),
-  STUNNEL_PORT(Integer.class, Integer.valueOf(7843)),
-
-  // deprecated params, for backward compatability when reading config
-  AUTHZ_CONFIG_FILENAME(String.class, "../../../../conf/FlexAuthz.xml"),
-  CONNECTOR_MANAGER_URLS(StringSet.class, new StringSet(ImmutableSet.<String>of()));
-
-  private final Class<?> valueClass;
-  private final Object defaultValue;
-
-  private ParamName(Class<?> valueClass, Object defaultValue) {
-    Preconditions.checkNotNull(valueClass);
-    Preconditions.checkArgument(valueClass.isInstance(defaultValue));
-    this.valueClass = valueClass;
-    this.defaultValue = defaultValue;
-  }
-
-  /**
-   * @return The value class for this parameter.
-   */
-  public Class<?> getValueClass() {
-    return valueClass;
-  }
-
-  /**
-   * @return The default value for this parameter.
-   */
-  public Object getDefaultValue() {
-    return defaultValue;
-  }
-
-  /**
-   * Is a given object a valid value for this key?
-   *
-   * @param value The object to check.
-   * @return True only if it would be a valid value.
-   */
-  public boolean isValidValue(Object value) {
-    return valueClass.isInstance(value);
-  }
-
-  /**
-   * Given a string representing a value for this key, converts it to an
-   * object.
-   *
-   * @param value The string to convert.
-   * @param valueClass The class of object to convert it to.
-   * @return The converted value.
-   * @throws IllegalArgumentException if the string can't be converted, or if
-   *     the value class is inappropriate for this parameter.
-   */
-  public <T> T stringToValue(String value, Class<T> valueClass) {
-    Preconditions.checkNotNull(value);
-    Preconditions.checkArgument(valueClass.isAssignableFrom(this.valueClass));
-    if (this.valueClass == String.class) {
-      return valueClass.cast(value);
-    }
-    try {
-      if (this.valueClass == Integer.class) {
-        return valueClass.cast(Integer.valueOf(value));
-      }
-      if (this.valueClass == Float.class) {
-        return valueClass.cast(Float.valueOf(value));
-      }
-    } catch (NumberFormatException e) {
-      throw new IllegalArgumentException(e);
-    }
-    if (this.valueClass == ConnMgrInfo.class) {
-      return valueClass.cast(ConnMgrInfo.valueOf(value));
-    }
-    if (this.valueClass == StringSet.class) {
-      return valueClass.cast(StringSet.valueOf(value));
-    }
-    throw new IllegalStateException("Unknown value class: " + valueClass.getName());
-  }
-
-  private static final class StringSet implements Iterable<String> {
-
-    final ImmutableSet<String> contents;
-
-    StringSet(ImmutableSet<String> contents) {
-      this.contents = ImmutableSet.copyOf(contents);
-    }
-
-    @Override
-    public Iterator<String> iterator() {
-      return contents.iterator();
-    }
-
-    /**
-     * Decodes a string-encoded string set.
-     *
-     * @param string The encoded string set.
-     * @return The decoded string set.
-     */
-    public static StringSet valueOf(String string) {
-      return ConfigSingleton.getGson().fromJson(string, StringSet.class);
-    }
-
-    @Override
-    public boolean equals(Object object) {
-      if (this == object) { return true; }
-      if (!(object instanceof StringSet)) { return false; }
-      StringSet other = (StringSet) object;
-      return Objects.equal(contents, other.contents);
-    }
-
-    @Override
-    public int hashCode() {
-      return Objects.hashCode(contents);
-    }
-
-    @Override
-    public String toString() {
-      return ConfigSingleton.getGson().toJson(this);
-    }
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(new TypeToken<ImmutableSet<String>>() {}.getType(),
-        TypeAdapters.immutableSet());
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/SecurityManagerConfig.java b/src/com/google/enterprise/secmgr/config/SecurityManagerConfig.java
deleted file mode 100644
index e070283..0000000
--- a/src/com/google/enterprise/secmgr/config/SecurityManagerConfig.java
+++ /dev/null
@@ -1,454 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Objects;
-import com.google.common.base.Pair;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-import com.google.gson.annotations.SerializedName;
-import com.google.gson.reflect.TypeToken;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Locale;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.annotation.concurrent.ThreadSafe;
-
-/**
- * A class that holds a complete security manager configuration.
- */
-@ThreadSafe
-public final class SecurityManagerConfig {
-
-  static final int CURRENT_VERSION = 5;
-
-  private final int version;
-  @GuardedBy("this") private ImmutableList<CredentialGroup> credentialGroups;
-  @GuardedBy("this") private ImmutableList<AuthnMechanism> mechanisms;
-  @GuardedBy("this") private ConfigParams params;
-  @GuardedBy("this") private FlexAuthorizer flexAuthorizer;
-
-  private SecurityManagerConfig(int version, ImmutableList<CredentialGroup> credentialGroups,
-      ConfigParams params, FlexAuthorizer flexAuthorizer) {
-    this.version = version;
-    setCredentialGroupsInternal(credentialGroups);
-    this.params = params;
-    this.flexAuthorizer = flexAuthorizer;
-  }
-
-  /**
-   * Set a configuration's credential groups.  The security manager uses this
-   * only for testing.
-   *
-   * @param credentialGroups The new credential groups.
-   * @throws IllegalArgumentException if there's a problem with the argument.
-   */
-  public void setCredentialGroupsInternal(ImmutableList<CredentialGroup> credentialGroups) {
-    ImmutableList.Builder<AuthnMechanism> mechanismsBuilder = ImmutableList.builder();
-    for (CredentialGroup credentialGroup : credentialGroups) {
-      mechanismsBuilder.addAll(credentialGroup.getMechanisms());
-    }
-    ImmutableList<AuthnMechanism> mechanisms = mechanismsBuilder.build();
-    synchronized (this) {
-      this.credentialGroups = credentialGroups;
-      this.mechanisms = mechanisms;
-    }
-  }
-
-  /**
-   * Make a security manager configuration.
-   *
-   * @param credentialGroups The configuration's credential groups.
-   * @param params The configuration's parameters.
-   * @param flexAuthorizer The flex authorization configs
-   * @return A security manager configuration.
-   */
-  public static SecurityManagerConfig make(Iterable<CredentialGroup> credentialGroups,
-      ConfigParams params, FlexAuthorizer flexAuthorizer) {
-    Preconditions.checkArgument(params != null);
-    Preconditions.checkArgument(flexAuthorizer != null);
-    return new SecurityManagerConfig(CURRENT_VERSION, checkCredentialGroups(credentialGroups),
-        params, flexAuthorizer);
-  }
-
-  @VisibleForTesting
-  public static SecurityManagerConfig make(Iterable<CredentialGroup> credentialGroups) {
-    return new SecurityManagerConfig(CURRENT_VERSION, checkCredentialGroups(credentialGroups),
-        ConfigParams.makeDefault(),
-        FlexAuthorizerImpl.makeDefault());
-  }
-
-  static SecurityManagerConfig makeInternal(int version, Iterable<CredentialGroup> credentialGroups,
-      ConfigParams params, FlexAuthorizer flexAuthorizer) {
-    Preconditions.checkArgument(version > 0 && version <= CURRENT_VERSION);
-    return new SecurityManagerConfig(
-        version,
-        checkCredentialGroups(credentialGroups),
-        (params != null) ? params : ConfigParams.makeDefault(),
-        (flexAuthorizer != null) ? flexAuthorizer : FlexAuthorizerImpl.makeDefault());
-  }
-
-  private static ImmutableList<CredentialGroup> checkCredentialGroups(
-      Iterable<CredentialGroup> credentialGroups) {
-    Preconditions.checkNotNull(credentialGroups);
-    ImmutableList<CredentialGroup> copy = ImmutableList.copyOf(credentialGroups);
-    Collection<String> names = Lists.newArrayList();
-    for (CredentialGroup group : copy) {
-      checkConfigName(group.getName(), names);
-      for (AuthnMechanism mech : group.getMechanisms()) {
-        checkConfigName(mech.getName(), names);
-      }
-    }
-    return copy;
-  }
-
-  private static void checkConfigName(String name, Collection<String> names) {
-    if (name != null) {
-      name = name.toLowerCase(Locale.US);
-      Preconditions.checkArgument(!names.contains(name),
-          "Configuration name appears more than once: %s", name);
-      names.add(name);
-    }
-  }
-
-  /**
-   * @return A default security manager configuration.
-   */
-  public static SecurityManagerConfig makeDefault() {
-    return SecurityManagerConfig.make(
-        makeDefaultCredentialGroups(),
-        ConfigParams.makeDefault(),
-        FlexAuthorizerImpl.makeDefault());
-  }
-
-  public static ImmutableList<CredentialGroup> makeDefaultCredentialGroups() {
-    return ImmutableList.of(CredentialGroup.builder().build());
-  }
-
-  /**
-   * @return The configuration's version.
-   */
-  int getVersion() {
-    return version;
-  }
-
-  /**
-   * Gets the credential groups contained in this configuration.
-   *
-   * @return The credential groups as an immutable list.  The order is the same
-   *     as was given when this configuration was created.
-   */
-  public synchronized ImmutableList<CredentialGroup> getCredentialGroups() {
-    return credentialGroups;
-  }
-
-  /**
-   * Set a configuration's credential groups.  The security manager uses this
-   * only for testing.
-   *
-   * @param credentialGroups The new credential groups.
-   * @throws IllegalArgumentException if there's a problem with the argument.
-   */
-  public void setCredentialGroups(Iterable<CredentialGroup> credentialGroups) {
-    setCredentialGroupsInternal(checkCredentialGroups(credentialGroups));
-    ConfigSingleton.setChanged();
-  }
-
-  /**
-   * Gets the authentication mechanisms contained in this configuration.
-   *
-   * @return The mechanisms as an immutable list.  The order is the same as was
-   *     given when this configuration was created.
-   */
-  public synchronized ImmutableList<AuthnMechanism> getMechanisms() {
-    return mechanisms;
-  }
-
-  /**
-   * Gets the credential group for a given mechanism.
-   *
-   * @param mechanism The mechanism to get the credential group for.
-   * @return The credential group for the given mechanism.
-   * @throws IllegalArgumentException if the mechanism isn't contained in this
-   *     configuration.
-   */
-  public CredentialGroup getCredentialGroup(AuthnMechanism mechanism) {
-    for (CredentialGroup credentialGroup : getCredentialGroups()) {
-      if (credentialGroup.getMechanisms().contains(mechanism)) {
-        return credentialGroup;
-      }
-    }
-    throw new IllegalArgumentException("Unknown mechanism: " + mechanism);
-  }
-
-  /**
-   * Gets the credential group with a given name.
-   *
-   * @param name The credential-group name to search for.
-   * @return The credential group with that name.
-   * @throws IllegalArgumentException if there's no credential group with that name.
-   */
-  public CredentialGroup getCredentialGroup(String name) {
-    Preconditions.checkNotNull(name);
-    for (CredentialGroup credentialGroup : getCredentialGroups()) {
-      if (name.equalsIgnoreCase(credentialGroup.getName())) {
-        return credentialGroup;
-      }
-    }
-    throw new IllegalArgumentException("No credential group with this name: " + name);
-  }
-
-  /**
-   * Gets an authority predicate for a given credential group.
-   *
-   * @param credentialGroup A credential group to get the predicate for.
-   * @return The authority predicate for the credential group.
-   * @throws IllegalArgumentException if the credential group isn't contained in
-   *     this configuration.
-   */
-  public Predicate<AuthnAuthority> getAuthorityPredicate(CredentialGroup credentialGroup) {
-    ImmutableSet.Builder<AuthnAuthority> builder = ImmutableSet.builder();
-    builder.add(credentialGroup.getAuthority());
-    for (AuthnMechanism mechanism : credentialGroup.getMechanisms()) {
-      builder.add(mechanism.getAuthority());
-    }
-    return Predicates.in(builder.build());
-  }
-
-  public synchronized FlexAuthorizer getFlexAuthorizer() {
-    return flexAuthorizer;
-  }
-
-  /**
-   * Sets this configurations's flex authorizer.  The security manager uses this
-   * only for testing.
-   */
-  public void setFlexAuthorizer(FlexAuthorizer flexAuthorizer) {
-    synchronized (this) {
-      this.flexAuthorizer = flexAuthorizer;
-    }
-    ConfigSingleton.setChanged();
-  }
-
-  /**
-   * @return The configuration parameters.
-   */
-  public synchronized ConfigParams getParams() {
-    return params;
-  }
-
-  /**
-   * Gets a list of credential group name and mechanism name pair for the mechanism.
-   *
-   * @param mechanismType the authentication mechanism type
-   * @return a list of credential group name and mechanism name pair for the mechanism.
-   */
-  public <T extends AuthnMechanism> List<Pair<String, String>> getMechanism(
-      final Class<T> mechanismType) {
-    List<Pair<String, String>> mechanisms = Lists.newArrayList();
-    for (CredentialGroup group : getCredentialGroups()) {
-      for (AuthnMechanism mech : group.getMechanisms()) {
-        if (mechanismType.isInstance(mech)) {
-          mechanisms.add(Pair.of(group.getName(), mech.getName()));
-        }
-      }
-    }
-    return mechanisms;
-  }
-
-  /**
-   * Checks if the mechanism is configured.
-   *
-   * @param mechanismType the authentication mechanism type
-   * @return true if the mechanism is already configured.
-   */
-  public <T extends AuthnMechanism> boolean hasMechanism(final Class<T> mechanismType) {
-    return !getMechanism(mechanismType).isEmpty();
-  }
-
-  /**
-   * Sets a configuration's parameters.  The security manager uses this only for
-   * testing.
-   *
-   * @param params The new parameters.
-   */
-  public void setParams(ConfigParams params) {
-    Preconditions.checkNotNull(params);
-    synchronized (this) {
-      this.params = params;
-    }
-    ConfigSingleton.setChanged();
-  }
-
-  /**
-   * @return The name of the ACL group rules file, never null or empty.
-   */
-  public String getAclGroupsFilename() {
-    return params.get(ParamName.ACL_GROUPS_FILENAME, String.class);
-  }
-
-  /**
-   * @return The name of the ACL URL rules file, never null or empty.
-   */
-  public String getAclUrlsFilename() {
-    return params.get(ParamName.ACL_URLS_FILENAME, String.class);
-  }
-
-  /**
-   * @return The name of the certificate-authority certificates file, never null
-   *     or empty.
-   */
-  public String getCertificateAuthoritiesFilename() {
-    return params.get(ParamName.CERTIFICATE_AUTHORITIES_FILENAME, String.class);
-  }
-
-  /**
-   * @return The boolean value whether to check the server certificate during
-   *     serving time
-   */
-  public Boolean getCheckServerCertificate() {
-    return params.get(ParamName.CHECK_SERVER_CERTIFICATE, Boolean.class);
-  }
-
-  /**
-   * @return The URLs of the configured connector managers as an immutable set.
-   */
-  public StringSet getConnectorManagerUrls() {
-    return params.get(ParamName.CONNECTOR_MANAGER_URLS, StringSet.class);
-  }
-
-  /**
-   * @return The name of the http deny rules file, never null or empty.
-   */
-  public String getDenyRulesFilename() {
-    return params.get(ParamName.DENY_RULES_FILENAME, String.class);
-  }
-
-  /**
-   * @return The global batch request timeout.
-   */
-  public Float getGlobalBatchRequestTimeout() {
-    return params.get(ParamName.GLOBAL_BATCH_REQUEST_TIMEOUT, Float.class);
-  }
-
-  /**
-   * @return The global single request timeout.
-   */
-  public Float getGlobalSingleRequestTimeout() {
-    return params.get(ParamName.GLOBAL_SINGLE_REQUEST_TIMEOUT, Float.class);
-  }
-
-  /**
-   * @return The name of the SAML metadata configuration file, never null or
-   *     empty.
-   */
-  public String getSamlMetadataFilename() {
-    return params.get(ParamName.SAML_METADATA_FILENAME, String.class);
-  }
-
-  /**
-   * @return The name of the security manager's certificate file, never null or
-   *     empty.
-   */
-  public String getServerCertificateFilename() {
-    return params.get(ParamName.SERVER_CERTIFICATE_FILENAME, String.class);
-  }
-
-  /**
-   * @return The name of the certificate file to be used for signing outgoing
-   *     messages, never null or empty.
-   */
-  public String getSigningCertificateFilename() {
-    return params.get(ParamName.SIGNING_CERTIFICATE_FILENAME, String.class);
-  }
-
-  /**
-   * @return The name of the key file to be used for signing outgoing messages,
-   *     never null or empty.
-   */
-  public String getSigningKeyFilename() {
-    return params.get(ParamName.SIGNING_KEY_FILENAME, String.class);
-  }
-
-  /**
-   * @return The port of the stunnel service that is forwarding to the security manager.
-   */
-  public int getStunnelPort() {
-    return params.get(ParamName.STUNNEL_PORT, Integer.class);
-  }
-
-  @Override
-  public String toString() {
-    return ConfigSingleton.getGson().toJson(this);
-  }
-
-  @Override
-  public synchronized boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof SecurityManagerConfig)) { return false; }
-    SecurityManagerConfig other = (SecurityManagerConfig) object;
-    return Objects.equal(getVersion(), other.getVersion())
-        && Objects.equal(getCredentialGroups(), other.getCredentialGroups())
-        && Objects.equal(getParams(), other.getParams())
-        && Objects.equal(getFlexAuthorizer(), other.getFlexAuthorizer());
-  }
-
-  @Override
-  public synchronized int hashCode() {
-    return Objects.hashCode(getVersion(), getCredentialGroups(), getParams(), getFlexAuthorizer());
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(SecurityManagerConfig.class,
-        ProxyTypeAdapter.make(SecurityManagerConfig.class, LocalProxy.class));
-    builder.registerTypeAdapter(new TypeToken<ImmutableList<CredentialGroup>>() {}.getType(),
-        TypeAdapters.immutableList());
-  }
-
-  private static final class LocalProxy implements TypeProxy<SecurityManagerConfig> {
-    int version;
-    @SerializedName("CGs") ImmutableList<CredentialGroup> credentialGroups;
-    ConfigParams params;
-    @SerializedName("flexAuthz") FlexAuthorizer flexAuthorizer;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(SecurityManagerConfig config) {
-      version = config.getVersion();
-      credentialGroups = config.getCredentialGroups();
-      params = config.getParams();
-      flexAuthorizer = config.getFlexAuthorizer();
-    }
-
-    @Override
-    public SecurityManagerConfig build() {
-      return makeInternal(version, credentialGroups, params, flexAuthorizer);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/config/StringSet.java b/src/com/google/enterprise/secmgr/config/StringSet.java
deleted file mode 100644
index db6bdea..0000000
--- a/src/com/google/enterprise/secmgr/config/StringSet.java
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.config;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableSet;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-
-import java.util.Iterator;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * An implementation of Set&lt;String&gt; with a reliable string representation.
- */
-@Immutable
-public final class StringSet implements Iterable<String> {
-
-  private final ImmutableSet<String> contents;
-
-  private StringSet(ImmutableSet<String> contents) {
-    this.contents = contents;
-  }
-
-  /**
-   * Makes a new string set.
-   *
-   * @param contents The contents of the new set.
-   * @return A new set with the given contents.
-   */
-  public static StringSet make(Iterable<String> contents) {
-    return new StringSet(ImmutableSet.copyOf(contents));
-  }
-
-  /**
-   * Makes a new string set.
-   *
-   * @param contents The contents of the new set.
-   * @return A new set with the given contents.
-   */
-  public static StringSet make(String... contents) {
-    return new StringSet(ImmutableSet.copyOf(contents));
-  }
-
-  @Override
-  public Iterator<String> iterator() {
-    return contents.iterator();
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (this == object) { return true; }
-    if (!(object instanceof StringSet)) { return false; }
-    StringSet other = (StringSet) object;
-    return Objects.equal(contents, other.contents);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hashCode(contents);
-  }
-
-  @Override
-  public String toString() {
-    return ConfigSingleton.getGson().toJson(this);
-  }
-
-  /**
-   * Decodes a string-encoded string set.
-   *
-   * @param string The encoded string set.
-   * @return The decoded string set.
-   */
-  public static StringSet valueOf(String string) {
-    return ConfigSingleton.getGson().fromJson(string, StringSet.class);
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(StringSet.class,
-        ProxyTypeAdapter.make(StringSet.class, LocalProxy.class));
-    builder.registerTypeAdapter(new TypeToken<ImmutableSet<String>>() {}.getType(),
-        TypeAdapters.immutableSet());
-  }
-
-  private static final class LocalProxy implements TypeProxy<StringSet> {
-    ImmutableSet<String> contents;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(StringSet set) {
-      contents = set.contents;
-    }
-
-    @Override
-    public StringSet build() {
-      return make(contents);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/http/ConnectorUtil.java b/src/com/google/enterprise/secmgr/http/ConnectorUtil.java
deleted file mode 100644
index 7ced38b..0000000
--- a/src/com/google/enterprise/secmgr/http/ConnectorUtil.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * 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.secmgr.http;
-
-import static com.google.enterprise.secmgr.common.XmlUtil.findChildElement;
-import static com.google.enterprise.secmgr.common.XmlUtil.getChildElementText;
-import static com.google.enterprise.secmgr.common.XmlUtil.getChildElements;
-import static com.google.enterprise.secmgr.common.XmlUtil.isElementWithQname;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.enterprise.secmgr.common.XmlUtil;
-import com.google.enterprise.secmgr.config.ConfigSingleton;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.ls.LSException;
-import org.w3c.dom.ls.LSSerializer;
-
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.StringWriter;
-import java.net.URL;
-import java.util.Map;
-import java.util.Observable;
-import java.util.Observer;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.xml.namespace.QName;
-
-public final class ConnectorUtil {
-
-  // Don't instantiate.
-  private ConnectorUtil() {
-    throw new UnsupportedOperationException();
-  }
-
-  private static final Logger LOGGER = Logger.getLogger(ConnectorUtil.class.getName());
-
-  private static QName cmname(String localPart) {
-    return new QName(localPart);
-  }
-
-  // All of these QName constants are exposed for testing.
-  public static final QName XML_TAG_ANSWER = cmname("Answer");
-  public static final QName XML_TAG_AUTHN_CREDENTIAL = cmname("Credentials");
-  public static final QName XML_TAG_AUTHN_DOMAIN = cmname("Domain");
-  public static final QName XML_TAG_AUTHN_PASSWORD = cmname("Password");
-  public static final QName XML_TAG_AUTHN_REQUEST = cmname("AuthnRequest");
-  public static final QName XML_TAG_AUTHN_RESPONSE = cmname("AuthnResponse");
-  public static final QName XML_TAG_AUTHN_USERNAME = cmname("Username");
-  public static final QName XML_TAG_AUTHZ_QUERY = cmname("AuthorizationQuery");
-  public static final QName XML_TAG_AUTHZ_RESPONSE = cmname("AuthorizationResponse");
-  public static final QName XML_TAG_CONNECTORS = cmname("Connectors");
-  public static final QName XML_TAG_CONNECTOR_INSTANCE = cmname("ConnectorInstance");
-  public static final QName XML_TAG_CONNECTOR_INSTANCES = cmname("ConnectorInstances");
-  public static final QName XML_TAG_CONNECTOR_NAME = cmname("ConnectorName");
-  public static final QName XML_TAG_CONNECTOR_QUERY = cmname("ConnectorQuery");
-  public static final QName XML_TAG_CONNECTOR_TYPE = cmname("ConnectorType");
-  public static final QName XML_TAG_DECISION = cmname("Decision");
-  public static final QName XML_TAG_FAILURE = cmname("Failure");
-  public static final QName XML_TAG_GROUP = cmname("Group");
-  public static final QName XML_TAG_IDENTITY = cmname("Identity");
-  public static final QName XML_TAG_INFO = cmname("Info");
-  public static final QName XML_TAG_RESOURCE = cmname("Resource");
-  public static final QName XML_TAG_RESPONSE_ROOT = cmname("CmResponse");
-  public static final QName XML_TAG_STATUS_ID = cmname("StatusId");
-  public static final QName XML_TAG_SUCCESS = cmname("Success");
-
-  // The connector name attribute should be lower case, however the
-  // connector manager used this form so we have to change to the current.
-  public static final QName XML_ATTR_CONNECTOR_NAME = cmname("ConnectorName");
-
-  public static final QName XML_ATTR_DOMAIN = cmname("domain");
-  public static final QName XML_ATTR_PASSWORD = cmname("password");
-
-  public static final String CONFIG_XML_DECLARATION = "xml-declaration";
-
-  public static final String DECISION_TEXT_PERMIT = "permit";
-  public static final String DECISION_TEXT_DENY = "deny";
-  public static final String DECISION_TEXT_INDETERMINATE = "indeterminate";
-
-  public static final String CM_AUTHENTICATE_SERVLET_PATH = "/authenticate";
-  public static final String CM_AUTHORIZATION_SERVLET_PATH = "/authorization";
-  public static final String CM_INSTANCE_LIST_SERVLET_PATH = "/getConnectorInstanceList";
-
-  public static final String LOG_RESPONSE_EMPTY_NODE = "Empty node";
-
-  public static final int SUCCESS = 0;
-  public static final int RESPONSE_EMPTY_NODE = 5213;
-  public static final int RESPONSE_NULL_CONNECTOR = 5215;
-  public static final int ERROR_PARSING_XML_REQUEST = 5300;
-
-  @GuardedBy("class") private static Map<String, String> urlMap;
-  @GuardedBy("class") private static boolean isInitialized;
-
-  public static synchronized void initialize() {
-    if (!isInitialized) {
-      ConfigSingleton.getObservable().addObserver(LOCAL_OBSERVER);
-      isInitialized = true;
-    }
-  }
-
-  @VisibleForTesting
-  public static synchronized void initializeForTesting(Map<String, String> urlMap) {
-    ConfigSingleton.getObservable().deleteObserver(LOCAL_OBSERVER);
-    ConnectorUtil.urlMap = urlMap;
-    isInitialized = true;
-  }
-
-  private static final Observer LOCAL_OBSERVER
-      = new Observer() {
-          @Override
-          public void update(Observable observable, Object object) {
-            reinitializeUrlMap();
-          }
-        };
-
-  private static void reinitializeUrlMap() {
-    ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
-    Iterable<String> urls;
-    try {
-      urls = ConfigSingleton.getConnectorManagerUrls();
-    } catch (IOException e) {
-      LOGGER.log(Level.SEVERE, "Unable to get list of connector manager URLs: ", e);
-      return;
-    }
-    for (String url : urls) {
-      Set<String> instances;
-      try {
-        instances = getInstances(url);
-      } catch (IOException e) {
-        LOGGER.log(Level.WARNING, "Unable to read connector instances from " + url + ": ", e);
-        continue;
-      }
-      for (String instance : instances) {
-        builder.put(instance, url);
-      }
-    }
-    synchronized (ConnectorUtil.class) {
-      urlMap = builder.build();
-    }
-  }
-
-  /**
-   * @return An immutable map from connector-instance name to connector-manager URL.
-   */
-  public static synchronized Map<String, String> getUrlMap() {
-    if (urlMap == null) {
-      reinitializeUrlMap();
-    }
-    return urlMap;
-  }
-
-  /**
-   * Gets the connector-manager URL associated with a given connector-instance name.
-   *
-   * @param instanceName The connector instance name to look up.
-   * @return The corresponding connector-manager URL, or null if none.
-   */
-  public static String getInstanceManagerUrl(String instanceName) {
-    return getUrlMap().get(instanceName);
-  }
-
-  /**
-   * Gets the connector-manager URL associated with a given connector-instance name.
-   *
-   * @param instanceName The connector instance name to look up.
-   * @return The corresponding connector-manager URL.
-   * @throws IllegalArgumentException if the URL is unknown.
-   */
-  public static String requireInstanceManagerUrl(String instanceName) {
-    String url = getInstanceManagerUrl(instanceName);
-    Preconditions.checkArgument(url != null);
-    return url;
-  }
-
-  /**
-   * Get a list of connector instances from a connector manager.
-   *
-   * @param managerUrl The URL for the connector manager.
-   * @return An immutable set of the instance names from the connector manager.
-   */
-  private static Set<String> getInstances(String managerUrl)
-      throws IOException {
-    Preconditions.checkNotNull(managerUrl);
-    return parseInstanceListResponse(doExchange(null, managerUrl + CM_INSTANCE_LIST_SERVLET_PATH,
-        -1));
-  }
-
-  private static Set<String> parseInstanceListResponse(Document document) {
-    Element root = document.getDocumentElement();
-    ImmutableSet.Builder<String> builder = ImmutableSet.builder();
-    if (!isElementWithQname(root, XML_TAG_RESPONSE_ROOT)) {
-      LOGGER.warning("Unexpected response from connector manager:" + root);
-      return builder.build();
-    }
-    Element instances = findChildElement(root, XML_TAG_CONNECTOR_INSTANCES, false);
-    if (instances != null) {
-      for (Element instance : getChildElements(instances, XML_TAG_CONNECTOR_INSTANCE)) {
-        builder.add(getChildElementText(instance, XML_TAG_CONNECTOR_NAME, true));
-      }
-    }
-    return builder.build();
-  }
-
-  /**
-   */
-  public static Document doExchange(Document request, String cmUrlString, int timeout)
-      throws IOException {
-    HttpExchange exchange = sendRequest(request, cmUrlString, timeout);
-    Document response;
-    try {
-      response = XmlUtil.getInstance().readXmlDocument(
-          new InputStreamReader(exchange.getResponseEntityAsStream(), "UTF-8"));
-    } finally {
-      exchange.close();
-    }
-    return response;
-  }
-
-  private static HttpExchange sendRequest(Document request, String cmUrlString, int timeout)
-      throws IOException {
-    HttpClientInterface httpClient = HttpClientUtil.getHttpClient();
-    HttpExchange exchange = httpClient.postExchange(new URL(cmUrlString), null);
-    if (timeout >= 0) {
-      exchange.setTimeout(timeout);
-    }
-    try {
-      exchange.setRequestHeader("Content-Type", "text/xml");
-      exchange.setRequestBody(documentToString(request).getBytes("UTF-8"));
-      int status = exchange.exchange();
-      if (status > 300) {
-        throw new IOException("Message exchange returned status: " + status);
-      }
-    } catch (IOException e) {
-      exchange.close();
-      throw e;
-    }
-    return exchange;
-  }
-
-  private static String documentToString(Document document)
-      throws IOException {
-    if (document == null) {
-      return "";
-    }
-    XmlUtil xmlUtil = XmlUtil.getInstance();
-    LSSerializer serializer = xmlUtil.makeSerializer();
-    // Don't generate <?xml ... ?> line.
-    serializer.getDomConfig().setParameter(CONFIG_XML_DECLARATION, false);
-    StringWriter output = new StringWriter();
-    try {
-      XmlUtil.writeXmlDocument(document, serializer, xmlUtil.getLsOutput(output));
-    } catch (LSException e) {
-      throw new IOException(e);
-    }
-    return output.toString();
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/http/HttpClientInterface.java b/src/com/google/enterprise/secmgr/http/HttpClientInterface.java
index b34c8b5..1689938 100644
--- a/src/com/google/enterprise/secmgr/http/HttpClientInterface.java
+++ b/src/com/google/enterprise/secmgr/http/HttpClientInterface.java
@@ -16,7 +16,6 @@
 
 import com.google.common.collect.ListMultimap;
 
-import java.io.IOException;
 import java.net.URL;
 
 import javax.annotation.Nonnull;
@@ -28,22 +27,6 @@
  */
 public interface HttpClientInterface {
   /**
-   * Create a new HTTP HEAD exchange object.
-   *
-   * @param url The URL to send the request to.
-   * @return A new HTTP exchange object.
-   */
-  public HttpExchange headExchange(@Nonnull URL url);
-
-  /**
-   * Create a new HTTP GET exchange object.
-   *
-   * @param url The URL to send the request to.
-   * @return A new HTTP exchange object.
-   */
-  public HttpExchange getExchange(@Nonnull URL url);
-
-  /**
    * Create a new HTTP POST exchange object.
    *
    * @param url The URL to send the request to.
@@ -52,79 +35,4 @@
    */
   public HttpExchange postExchange(@Nonnull URL url,
       @Nullable ListMultimap<String, String> parameters);
-
-  /**
-   * Create a new HTTP GET or HEAD exchange object.
-   * The method (GET or HEAD) is determined by the configuration for the URL.
-   *
-   * @param url The URL to send the request to.
-   * @return A new HTTP exchange object.
-   */
-  public HttpExchange newHttpExchange(@Nonnull URL url);
-
-  /**
-   * A marker type for an object representing an HTTP connection.
-   */
-  public interface Connection {
-
-    /**
-     * Close the connection.  After calling this method, the connection can't
-     * be used for further communication.
-     */
-    public void close() throws IOException;
-  }
-
-  /**
-   * Get a persistent connection for a given URL.
-   * The returned connection may be used multiple times.
-   * Calling this twice returns two different connections.
-   *
-   * @param url A URL specifying where to connect to.
-   * @return A new connection to the specified host.
-   */
-  public Connection getConnection(@Nonnull URL url) throws IOException;
-
-  /**
-   * Create a new HTTP HEAD exchange object.
-   *
-   * @param connection The connection to send the request over.
-   * @param url The URL to send the request to.
-   * @return A new HTTP exchange object.
-   */
-  public HttpExchange headExchange(@Nullable Connection connection, @Nonnull URL url);
-
-  /**
-   * Create a new HTTP GET exchange object.
-   *
-   * @param connection The connection to send the request over.
-   * @param url The URL to send the request to.
-   * @return A new HTTP exchange object.
-   */
-  public HttpExchange getExchange(@Nullable Connection connection, @Nonnull URL url);
-
-  /**
-   * Create a new HTTP POST exchange object.
-   *
-   * @param connection The connection to send the request over.
-   * @param url The URL to send the request to.
-   * @param parameters The POST parameters.
-   * @return A new HTTP exchange object.
-   */
-  public HttpExchange postExchange(@Nullable Connection connection, @Nonnull URL url,
-      @Nullable ListMultimap<String, String> parameters);
-
-  /**
-   * Create a new HTTP GET or HEAD exchange object.
-   * The method (GET or HEAD) is determined by the configuration for the URL.
-   *
-   * @param connection The connection to send the request over.
-   * @param url The URL to send the request to.
-   * @return A new HTTP exchange object.
-   */
-  public HttpExchange newHttpExchange(@Nullable Connection connection, @Nonnull URL url);
-
-  /**
-   * Sets connection timeout and socket timeout.
-   */
-  public void setRequestTimeoutMillis(int millisec);
 }
diff --git a/src/com/google/enterprise/secmgr/http/HttpClientUtil.java b/src/com/google/enterprise/secmgr/http/HttpClientUtil.java
deleted file mode 100644
index 613edb5..0000000
--- a/src/com/google/enterprise/secmgr/http/HttpClientUtil.java
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.http;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.enterprise.secmgr.common.CookieStore;
-import com.google.enterprise.secmgr.common.GCookie;
-import com.google.enterprise.secmgr.common.HttpUtil;
-import com.google.enterprise.secmgr.config.ConfigSingleton;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.annotation.concurrent.ThreadSafe;
-
-/**
- * Utilities useful throughout the security manager.
- */
-@ThreadSafe
-public class HttpClientUtil {
-
-  // don't instantiate
-  private HttpClientUtil() {
-    throw new UnsupportedOperationException();
-  }
-
-  @GuardedBy("class") private static HttpClientInterface clientOverride = null;
-
-  /**
-   * Get an HTTP client to use when communicating with client servers.
-   *
-   * @return An HTTP client.
-   */
-  public static HttpClientInterface getHttpClient() {
-    synchronized (HttpClientUtil.class) {
-      if (clientOverride != null) {
-        return clientOverride;
-      }
-    }
-    return ConfigSingleton.getInstance(HttpClientInterface.class);
-  }
-
-  /**
-   * Set the HTTP client to use when communicating with client servers.  To be
-   * used by unit tests to override the default transport mechanism.
-   *
-   * @param client An HTTP client.
-   */
-  @VisibleForTesting
-  public static void setHttpClient(HttpClientInterface client) {
-    Preconditions.checkNotNull(client);
-    synchronized (HttpClientUtil.class) {
-      clientOverride = client;
-    }
-  }
-
-  /**
-   * Return the redirect location of an HTTP response.
-   *
-   * @param exchange The HTTP exchange object containing the response.
-   * @return The URL from a <code>Refresh</code> or <code>Location</code>
-   *     header, or null if none such.
-   */
-  public static String getRedirectUrl(HttpExchange exchange) {
-    int status = exchange.getStatusCode();
-    if (HttpUtil.isGoodHttpStatus(status)) {
-      return HttpClientUtil.getRefreshUrl(exchange);
-    }
-    if (status >= 300 && status < 400) {
-      return exchange.getResponseHeaderValue("Location");
-    }
-    return null;
-  }
-
-  /**
-   * Get the relative URL string in Refresh header if exists.
-   * @param exchange The HTTP exchange object.
-   * @return The relative URL string of Refresh header or null
-   *   if none exists
-   */
-  private static String getRefreshUrl(HttpExchange exchange) {
-    String refresh = exchange.getResponseHeaderValue("Refresh");
-    if (refresh != null) {
-      int pos = refresh.indexOf(';');
-      if (pos != -1) {
-        // found a semicolon
-        String timeToRefresh = refresh.substring(0, pos);
-        if ("0".equals(timeToRefresh)) {
-          // only follow this if its an immediate refresh (0 seconds)
-          pos = refresh.indexOf('=');
-          if (pos != -1 && (pos + 1) < refresh.length()) {
-            return refresh.substring(pos + 1);
-          }
-        }
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Parses cookies from the headers of an HTTP response.
-   *
-   * @param exchange The exchange to get the response headers from.
-   * @param sessionId A session ID to add to log messages.
-   * @param store A cookie store to which the parsed cookies will be added.
-   */
-  public static void parseHttpResponseCookies(HttpExchange exchange, String sessionId,
-      CookieStore store) {
-    GCookie.parseResponseHeaders(
-        exchange.getResponseHeaderValues(HttpUtil.HTTP_HEADER_SET_COOKIE),
-        HttpUtil.toUri(exchange.getUrl()),
-        sessionId,
-        store);
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/http/HttpExchange.java b/src/com/google/enterprise/secmgr/http/HttpExchange.java
index 969ec96..c3b0b29 100644
--- a/src/com/google/enterprise/secmgr/http/HttpExchange.java
+++ b/src/com/google/enterprise/secmgr/http/HttpExchange.java
@@ -15,8 +15,6 @@
 package com.google.enterprise.secmgr.http;
 
 import com.google.common.collect.ListMultimap;
-import com.google.enterprise.secmgr.common.CookieStore;
-import com.google.enterprise.secmgr.common.GCookie;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -123,23 +121,6 @@
   public String getRequestHeaderValue(String headerName);
 
   /**
-   * Adds cookies to this exchange's request.
-   *
-   * @param cookies The cookies to add.
-   */
-  public void addCookies(Iterable<GCookie> cookies);
-
-  /**
-   * Gets this exchange's cookies.  Prior to calling {@link #exchange} this will
-   * return the request cookies; subsequently it will return cookies as modified
-   * by the response.
-   *
-   * @return The exchange's cookie store.
-   */
-  @Nonnull
-  public CookieStore getCookies();
-
-  /**
    * Sets the entity of the request.
    *
    * @param byteArrayRequestEntity The bytes to use as an entity.
diff --git a/src/com/google/enterprise/secmgr/identity/AbstractCredential.java b/src/com/google/enterprise/secmgr/identity/AbstractCredential.java
deleted file mode 100644
index a311a15..0000000
--- a/src/com/google/enterprise/secmgr/identity/AbstractCredential.java
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.identity;
-
-import com.google.common.base.Predicate;
-import com.google.enterprise.secmgr.config.ConfigSingleton;
-
-/**
- * A base class for all credentials.
- *
- * @see Credential
- */
-public abstract class AbstractCredential implements Credential {
-
-  /**
-   * Get a predicate for a given credential subtype.  This predicate is true
-   * only of credentials of that type.
-   *
-   * @param clazz The class of the credential subtype to test for.
-   * @return The requested predicate.
-   */
-  public static final Predicate<Credential> getTypePredicate(
-      final Class<? extends Credential> clazz) {
-    return new Predicate<Credential>() {
-      public boolean apply(Credential credential) {
-        return clazz.isInstance(credential);
-      }
-    };
-  }
-
-  @Override
-  public String toString() {
-    return ConfigSingleton.getGson().toJson(this);
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/identity/AuthnPrincipal.java b/src/com/google/enterprise/secmgr/identity/AuthnPrincipal.java
deleted file mode 100644
index dbe136a..0000000
--- a/src/com/google/enterprise/secmgr/identity/AuthnPrincipal.java
+++ /dev/null
@@ -1,206 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.identity;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.enterprise.secmgr.common.Stringify;
-import com.google.enterprise.secmgr.config.CredentialTypeName;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * A credential that contains the user's name and optionally some domain info.
- *
- * A principal may be stored in an identity's credential set.  Doing so doesn't
- * imply that it's verified; that's true only if the identity has a verification
- * that explicitly includes the principal.
- *
- * @see Verification
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public final class AuthnPrincipal extends AbstractCredential
-    implements java.security.Principal {
-
-  @Nonnull private final String name;
-  @Nullable private final String activeDirectoryDomain;
-
-  private AuthnPrincipal(String name, @Nullable String activeDirectoryDomain) {
-    super();
-    Preconditions.checkNotNull(name);
-    this.name = name;
-    this.activeDirectoryDomain = activeDirectoryDomain;
-  }
-
-  /**
-   * Makes a principal.
-   *
-   * @param name The principal's name; may not be null.
-   * @param activeDirectoryDomain The ActiveDirectory domain name; may be null.
-   * @return A principal with the given components.
-   */
-  @Nonnull
-  public static AuthnPrincipal make(String name, @Nullable String activeDirectoryDomain) {
-    return new AuthnPrincipal(name, activeDirectoryDomain);
-  }
-
-  /**
-   * Makes a principal with no domain.
-   *
-   * @param name The username.
-   * @return A principal with the given username and no domain.
-   */
-  @Nonnull
-  public static AuthnPrincipal make(String name) {
-    return new AuthnPrincipal(name, null);
-  }
-
-  /**
-   * Gets the name associated with this identity.  Usually a "user name" or
-   * "login name".
-   *
-   * @return The identity's name as a string.
-   */
-  @Nonnull
-  public String getName() {
-    return name;
-  }
-
-  /**
-   * Gets the Active Directory Domain name associated with this identity.
-   *
-   * @return The domain name as a string.
-   */
-  @Nullable
-  public String getActiveDirectoryDomain() {
-    return activeDirectoryDomain;
-  }
-
-  @Override
-  public boolean isPublic() {
-    return true;
-  }
-
-  @Override
-  public CredentialTypeName getTypeName() {
-    return CredentialTypeName.PRINCIPAL;
-  }
-
-  @Override
-  public boolean isVerifiable() {
-    return !name.isEmpty();
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof AuthnPrincipal)) { return false; }
-    AuthnPrincipal principal = (AuthnPrincipal) object;
-    return Objects.equal(name, principal.getName())
-        && Objects.equal(activeDirectoryDomain, principal.getActiveDirectoryDomain());
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hashCode(name, activeDirectoryDomain);
-  }
-
-  @Override
-  public String toString() {
-    return "{principal: " + Stringify.object(joinUsernameDomain(name, activeDirectoryDomain)) + "}";
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(AuthnPrincipal.class,
-        ProxyTypeAdapter.make(AuthnPrincipal.class, LocalProxy.class));
-  }
-
-  private static final class LocalProxy implements TypeProxy<AuthnPrincipal> {
-    String name;
-    String activeDirectoryDomain;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(AuthnPrincipal principal) {
-      name = principal.getName();
-      activeDirectoryDomain = principal.getActiveDirectoryDomain();
-    }
-
-    @Override
-    public AuthnPrincipal build() {
-      return make(name, activeDirectoryDomain);
-    }
-  }
-
-  /**
-   * Parses a string into a principal.
-   *
-   * @param string The combined username/domain string.
-   * @return A principal with the separated username and domain.
-   * @see #parseUsernameDomain
-   */
-  @Nonnull
-  public static AuthnPrincipal parse(String string) {
-    String[] parsed = parseUsernameDomain(string);
-    return make(parsed[0], parsed[1]);
-  }
-
-  /**
-   * Parses a string into a username/domain pair.
-   *
-   * @param string The combined username/domain string.
-   * @return The username and domain strings as an array.
-   */
-  @Nonnull
-  public static String[] parseUsernameDomain(String string) {
-    Preconditions.checkNotNull(string);
-    int slash = string.indexOf("\\");
-    if (slash == -1) {
-      slash = string.indexOf("/");
-    }
-    if (slash >= 0) {
-      return new String[] { string.substring(slash + 1), string.substring(0, slash) };
-    }
-    int atSign = string.indexOf("@");
-    if (atSign >= 0) {
-      return new String[] { string.substring(0, atSign), string.substring(atSign + 1) };
-    }
-    return new String[] { string, null };
-  }
-
-  /**
-   * Joins a username and domain into a string.
-   *
-   * @param username The username.
-   * @param domain The domain, or {@code null} if none.
-   * @return The combined username/domain string.
-   */
-  @Nonnull
-  public static String joinUsernameDomain(String username, @Nullable String domain) {
-    Preconditions.checkNotNull(username);
-    return (Strings.isNullOrEmpty(domain)) ? username : username + "@" + domain;
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/identity/CredPassword.java b/src/com/google/enterprise/secmgr/identity/CredPassword.java
deleted file mode 100644
index ab2de0a..0000000
--- a/src/com/google/enterprise/secmgr/identity/CredPassword.java
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.identity;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.enterprise.secmgr.config.CredentialTypeName;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-import com.google.gson.annotations.SerializedName;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * A credential consisting of a password.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public final class CredPassword extends AbstractCredential {
-
-  @Nonnull private final String text;
-
-  private CredPassword(String text) {
-    Preconditions.checkNotNull(text);
-    this.text = text;
-  }
-
-  /**
-   * Gets a password credential for a given password text.
-   *
-   * @param text The text of the password.
-   * @return A corresponding password credential.
-   */
-  @Nonnull
-  public static CredPassword make(String text) {
-    return new CredPassword(text);
-  }
-
-  @Override
-  public boolean isPublic() {
-    return false;
-  }
-
-  @Override
-  public CredentialTypeName getTypeName() {
-    return CredentialTypeName.PASSWORD;
-  }
-
-  @Override
-  public boolean isVerifiable() {
-    return !text.isEmpty();
-  }
-
-  /**
-   * Gets the user's password.
-   *
-   * @return The password text.
-   */
-  @Nonnull
-  public String getText() {
-    return text;
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof CredPassword)) { return false; }
-    CredPassword credential = (CredPassword) object;
-    return Objects.equal(text, credential.getText());
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hashCode(text);
-  }
-
-  @Override
-  public String toString() {
-    return "{password}";
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(CredPassword.class,
-        ProxyTypeAdapter.make(CredPassword.class, LocalProxy.class));
-  }
-
-  private static final class LocalProxy implements TypeProxy<CredPassword> {
-    @SerializedName("password") String text;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(CredPassword password) {
-      text = password.getText();
-    }
-
-    @Override
-    public CredPassword build() {
-      return make(text);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/identity/Credential.java b/src/com/google/enterprise/secmgr/identity/Credential.java
deleted file mode 100644
index b66dba8..0000000
--- a/src/com/google/enterprise/secmgr/identity/Credential.java
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.identity;
-
-import com.google.enterprise.secmgr.config.CredentialTypeName;
-
-/**
- * A credential.  Examples of credentials include: username, password, kerberos
- * ticket, X.509 certificate.
- */
-public interface Credential {
-
-  /**
-   * Is it OK for this credential to be shared with others?
-   *
-   * Examples of public credentials include: username, X.509 credential.
-   * Examples of private credentials include: password, private key.
-   *
-   * @return True if the credential is public, false if it's private.
-   */
-  public boolean isPublic();
-
-  /**
-   * @return The name of this credential's type.
-   */
-  public CredentialTypeName getTypeName();
-
-  /**
-   * @return True if the credential is verifiable.
-   */
-  public boolean isVerifiable();
-}
diff --git a/src/com/google/enterprise/secmgr/identity/CredentialModule.java b/src/com/google/enterprise/secmgr/identity/CredentialModule.java
deleted file mode 100644
index 08e7100..0000000
--- a/src/com/google/enterprise/secmgr/identity/CredentialModule.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * 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.secmgr.identity;
-
-import com.google.common.collect.ImmutableList;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.gson.GsonBuilder;
-
-/**
- * A module for top-level configuration of this package.
- */
-public final class CredentialModule {
-
-  // Don't instantiate.
-  private CredentialModule() {
-    throw new UnsupportedOperationException();
-  }
-
-  public static void registerTypeAdapters(GsonBuilder builder) {
-    AuthnPrincipal.registerTypeAdapters(builder);
-    CredPassword.registerTypeAdapters(builder);
-    GroupMemberships.registerTypeAdapters(builder);
-    Verification.registerTypeAdapters(builder);
-    builder.registerTypeAdapter(Credential.class,
-        TypeAdapters.dispatch(
-            ImmutableList.<Class<? extends Credential>>of(
-                AuthnPrincipal.class,
-                CredPassword.class,
-                GroupMemberships.class)));
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/identity/GroupMemberships.java b/src/com/google/enterprise/secmgr/identity/GroupMemberships.java
deleted file mode 100644
index 2aa365f..0000000
--- a/src/com/google/enterprise/secmgr/identity/GroupMemberships.java
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2010 Google Inc.
-//
-// 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.secmgr.identity;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-import com.google.enterprise.secmgr.common.Stringify;
-import com.google.enterprise.secmgr.config.CredentialTypeName;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * A credential that contains a set of authentication group memberships
- * (such as a list of LDAP groups) to which the subject belongs.
- *
- * Similar to principals, the presence of a GroupMemberships instance does not
- * imply the credential has been verified; that is true only if the identity
- * has a verification that explicitly includes this GroupMemberships.
- * @see Verification
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public final class GroupMemberships extends AbstractCredential {
-
-  @Nonnull private final ImmutableSet<String> groups;
-
-  private GroupMemberships(Iterable<String> groups) {
-    super();
-    Preconditions.checkNotNull(groups);
-    this.groups = ImmutableSet.copyOf(groups);
-    Preconditions.checkArgument(!this.groups.isEmpty());
-  }
-
-  /**
-   * Make a groups-membership set.
-   *
-   * @param groups The names of the groups.
-   * @return An instance with the given names.
-   */
-  @Nonnull public static GroupMemberships make(Iterable<String> groups) {
-    return new GroupMemberships(groups);
-  }
-
-  /**
-   * Gets a set of the contained group names.
-   *
-   * @return The group's names as an immutable set of strings.
-   */
-  @Nonnull
-  public ImmutableSet<String> getGroups() {
-    return groups;
-  }
-
-  @Override
-  public boolean isPublic() {
-    return true;
-  }
-
-  @Override
-  public CredentialTypeName getTypeName() {
-    return CredentialTypeName.GROUPS;
-  }
-
-  @Override
-  public boolean isVerifiable() {
-    return true;
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof GroupMemberships)) { return false; }
-    GroupMemberships g = (GroupMemberships) object;
-    return Objects.equal(groups, g.getGroups());
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hashCode(groups);
-  }
-
-  @Override
-  public String toString() {
-    return "{groups: " + Stringify.objects(groups) + "}";
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(GroupMemberships.class,
-        ProxyTypeAdapter.make(GroupMemberships.class, LocalProxy.class));
-    builder.registerTypeAdapter(new TypeToken<ImmutableSet<String>>() {}.getType(),
-        TypeAdapters.immutableSet());
-  }
-
-  private static final class LocalProxy implements TypeProxy<GroupMemberships> {
-    ImmutableSet<String> groups;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(GroupMemberships credential) {
-      groups = credential.getGroups();
-    }
-
-    @Override
-    public GroupMemberships build() {
-      return make(groups);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/identity/Verification.java b/src/com/google/enterprise/secmgr/identity/Verification.java
deleted file mode 100644
index b070ad8..0000000
--- a/src/com/google/enterprise/secmgr/identity/Verification.java
+++ /dev/null
@@ -1,705 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.identity;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.enterprise.secmgr.common.SecurityManagerUtil;
-import com.google.enterprise.secmgr.common.Stringify;
-import com.google.enterprise.secmgr.json.ProxyTypeAdapter;
-import com.google.enterprise.secmgr.json.TypeAdapters;
-import com.google.enterprise.secmgr.json.TypeProxy;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-
-import org.joda.time.DateTimeUtils;
-import org.joda.time.format.DateTimeFormatter;
-import org.joda.time.format.ISODateTimeFormat;
-
-import java.util.Arrays;
-import java.util.Collection;
-
-import javax.annotation.CheckReturnValue;
-import javax.annotation.Nonnegative;
-import javax.annotation.Nonnull;
-import javax.annotation.ParametersAreNonnullByDefault;
-import javax.annotation.concurrent.Immutable;
-
-/**
- * The structure that holds results from credential verification.
- */
-@Immutable
-@ParametersAreNonnullByDefault
-public final class Verification {
-
-  /**
-   * A value for a verification expiration time that means the verification
-   * doesn't expire.
-   */
-  public static final long NEVER_EXPIRES = -1;
-
-  /**
-   * A value for a verification expiration time that means the verification
-   * expires when the current servlet request is finished.
-   */
-  public static final long EXPIRES_AFTER_REQUEST = -2;
-
-  /**
-   * Used internally to limit values accepted when making a verification.
-   */
-  public static final long MINIMUM_EXPIRATION_VALUE = -2;
-
-  @Nonnull private final VerificationStatus status;
-  private final long expirationTime;
-  @Nonnull private final ImmutableSet<Credential> credentials;
-
-  private Verification(VerificationStatus status, long expirationTime,
-      Iterable<? extends Credential> credentials) {
-    Preconditions.checkNotNull(status);
-    Preconditions.checkArgument(expirationTime >= MINIMUM_EXPIRATION_VALUE);
-    Preconditions.checkNotNull(credentials);
-    this.status = status;
-    this.expirationTime = expirationTime;
-    this.credentials = ImmutableSet.copyOf(credentials);
-  }
-
-  /**
-   * Gets a verification object with VERIFIED status and given credentials.
-   *
-   * @param expirationTime The expiration time of this verification.
-   * @param credentials The credentials that the status applies to.
-   * @return A verification with the given components.
-   */
-  public static Verification verified(long expirationTime,
-      Iterable<? extends Credential> credentials) {
-    return new Verification(VerificationStatus.VERIFIED, expirationTime, credentials);
-  }
-
-  /**
-   * Gets a verification object with VERIFIED status and given credentials.
-   *
-   * @param expirationTime The expiration time of this verification.
-   * @param credentials The credentials that the status applies to.
-   * @return A verification with the given components.
-   */
-  public static Verification verified(long expirationTime, Credential... credentials) {
-    return verified(expirationTime, Arrays.asList(credentials));
-  }
-
-  /**
-   * Gets a verification object with REFUTED status and given credentials.
-   *
-   * @param credentials The credentials that the status applies to.
-   * @return A verification with the given components.
-   */
-  public static Verification refuted(Iterable<? extends Credential> credentials) {
-    return new Verification(VerificationStatus.REFUTED, EXPIRES_AFTER_REQUEST, credentials);
-  }
-
-  /**
-   * Gets a verification object with REFUTED status and no credentials.
-   *
-   * @return A verification with the given components.
-   */
-  public static Verification refuted() {
-    return refuted(ImmutableSet.<Credential>of());
-  }
-
-  @VisibleForTesting
-  public static Verification make(VerificationStatus status, long expirationTime,
-      Credential... credentials) {
-    return new Verification(status, expirationTime, Arrays.asList(credentials));
-  }
-
-  /**
-   * Gets the status of this verification.
-   *
-   * @return The verification's status.
-   */
-  @Nonnull
-  public VerificationStatus getStatus() {
-    return status;
-  }
-
-  /**
-   * Are the credentials valid?
-   *
-   * @return True if the credentials were verified and found valid.
-   */
-  public boolean isVerified() {
-    return status == VerificationStatus.VERIFIED;
-  }
-
-  /**
-   * Are the credentials invalid?
-   *
-   * @return True if the credentials were verified and found invalid.
-   */
-  public boolean isRefuted() {
-    return status == VerificationStatus.REFUTED;
-  }
-
-  /**
-   * Is the verification status indeterminate?
-   *
-   * @return True if the credentials were verified with indeterminate result.
-   */
-  public boolean isIndeterminate() {
-    return status == VerificationStatus.INDETERMINATE;
-  }
-
-  /**
-   * Gets the expiration time for this verification.  Positive is a time
-   * comparable to {@link System#currentTimeMillis}, zero means "already
-   * expired", negative means "never expires".
-   *
-   * @return The expiration time.
-   */
-  public long getExpirationTime() {
-    return expirationTime;
-  }
-
-  /**
-   * Has the verification expired based on the given time?
-   *
-   * @param now The reference time.
-   * @return True if the verification has expired.
-   */
-  public boolean hasExpired(long now) {
-    return expirationTime >= 0
-        && !SecurityManagerUtil.isRemoteOnOrAfterTimeValid(expirationTime, now);
-  }
-
-  /**
-   * Compares the expiration time of this verification with that of a given
-   * verification.  The result is a positive number if the expiration time of
-   * this verification is later than that of the other; a negative number if
-   * this time is earlier than that of the other; or zero if they are equal.
-   *
-   * @param other The verification to compare to.
-   * @return The comparison result.
-   */
-  @CheckReturnValue
-  public int compareExpirationTimes(Verification other) {
-    return compareExpirationTimes(getExpirationTime(), other.getExpirationTime());
-  }
-
-  /**
-   * Compares two expiration times.
-   *
-   * @param t1 The first expiration time.
-   * @param t2 The second expiration time.
-   * @return A negative number if {@code t1<t2}, a positive number if
-   *     {@code t1>t2}, or zero if {@code t1==t2}.
-   * @throws IllegalArgumentException if either of the arguments is not
-   *     recognized as an expiration time.
-   */
-  @CheckReturnValue
-  public static int compareExpirationTimes(long t1, long t2) {
-    Preconditions.checkArgument(t1 >= MINIMUM_EXPIRATION_VALUE);
-    Preconditions.checkArgument(t2 >= MINIMUM_EXPIRATION_VALUE);
-    if (t1 == t2) { return 0; }
-    if (t1 == NEVER_EXPIRES) { return 1; }
-    if (t2 == NEVER_EXPIRES) { return -1; }
-    if (t1 == 0) { return -1; }
-    if (t2 == 0) { return 1; }
-    if (t1 == EXPIRES_AFTER_REQUEST) { return -1; }
-    if (t2 == EXPIRES_AFTER_REQUEST) { return 1; }
-    return (t1 > t2) ? 1 : -1;
-  }
-
-  /**
-   * Gets the minimum expiration time for some given verifications.  Ignores any
-   * verifications that don't satisfy {@link #isVerified}.
-   *
-   * @param verifications Some verifications to test.
-   * @return The earliest expiration time for those verifications.  Returns
-   *     {@link #NEVER_EXPIRES} if there are no verifications.
-   */
-  @CheckReturnValue
-  public static long minimumExpirationTime(Iterable<Verification> verifications) {
-    long expirationTime = NEVER_EXPIRES;
-    for (Verification verification : verifications) {
-      if (verification.isVerified()
-          && compareExpirationTimes(verification.getExpirationTime(), expirationTime) < 0) {
-        expirationTime = verification.getExpirationTime();
-      }
-    }
-    return expirationTime;
-  }
-
-  /**
-   * Gets the maximum expiration time for some given verifications.  Ignores any
-   * verifications that don't satisfy {@link #isVerified}.
-   *
-   * @param verifications Some verifications to test.
-   * @return The latest expiration time for those verifications.  Returns
-   *     {@code 0} if there are no verifications.
-   */
-  @CheckReturnValue
-  public static long maximumExpirationTime(Iterable<Verification> verifications) {
-    long expirationTime = 0;
-    for (Verification verification : verifications) {
-      if (verification.isVerified()
-          && compareExpirationTimes(verification.getExpirationTime(), expirationTime) > 0) {
-        expirationTime = verification.getExpirationTime();
-      }
-    }
-    return expirationTime;
-  }
-
-  /**
-   * Gets the credentials that were verified.
-   *
-   * @return An immutable set of the credentials that underwent verification.
-   */
-  @Nonnull
-  public ImmutableSet<Credential> getCredentials() {
-    return credentials;
-  }
-
-  /**
-   * Does this verification contain a given credential?
-   *
-   * @param credential A credential to test for.
-   * @return True if the given credential is contained.
-   */
-  public boolean containsCredential(Credential credential) {
-    for (Credential v : credentials) {
-      if (v.equals(credential)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Does this verification contain all of some given credentials?
-   *
-   * @param credentials Some credentials to test for.
-   * @return True if all of the given credentials are contained.
-   */
-  public boolean containsAllCredentials(Iterable<? extends Credential> credentials) {
-    for (Credential credential : credentials) {
-      if (!containsCredential(credential)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  /**
-   * Does this verification contain any of some given credentials?
-   *
-   * @param credentials Some credentials to test for.
-   * @return True if any of the given credentials are contained.
-   */
-  public boolean containsAnyCredential(Iterable<? extends Credential> credentials) {
-    for (Credential credential : credentials) {
-      if (containsCredential(credential)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  @Override
-  public boolean equals(Object object) {
-    if (object == this) { return true; }
-    if (!(object instanceof Verification)) { return false; }
-    Verification verification = (Verification) object;
-    return Objects.equal(status, verification.getStatus())
-        && Objects.equal(credentials, verification.getCredentials());
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hashCode(status, credentials);
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder builder = new StringBuilder();
-    builder.append("{Verification: status=");
-    builder.append(status);
-    builder.append("; ");
-    if (expirationTime == NEVER_EXPIRES) {
-      builder.append("never expires");
-    } else if (expirationTime == EXPIRES_AFTER_REQUEST) {
-      builder.append("expires after request");
-    } else {
-      builder.append("expires at ");
-      builder.append(ISO8601_FORMAT.print(expirationTime));
-    }
-    if (!credentials.isEmpty()) {
-      builder.append("; credentials ");
-      builder.append(Stringify.objects(credentials));
-    }
-    builder.append("}");
-    return builder.toString();
-  }
-
-  private static final DateTimeFormatter ISO8601_FORMAT = ISODateTimeFormat.dateTime();
-
-  /**
-   * Gets a predicate that compares a verification's status to a given value.
-   *
-   * @param status A status to test for.
-   * @return The corresponding predicate.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Predicate<Verification> getStatusPredicate(VerificationStatus status) {
-    return Predicates.compose(Predicates.equalTo(status), GET_STATUS_FUNCTION);
-  }
-
-  private static final Function<Verification, VerificationStatus> GET_STATUS_FUNCTION =
-      new Function<Verification, VerificationStatus>() {
-        @Override
-        public VerificationStatus apply(Verification v) {
-          return v.getStatus();
-        }
-      };
-
-  /**
-   * Gets a predicate that tests whether a given verification has status
-   * {@link VerificationStatus#VERIFIED}.
-   *
-   * @return The predicate.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Predicate<Verification> isVerifiedPredicate() {
-    return IS_VERIFIED_PREDICATE;
-  }
-
-  private static final Predicate<Verification> IS_VERIFIED_PREDICATE
-      = getStatusPredicate(VerificationStatus.VERIFIED);
-
-  /**
-   * Gets a predicate that tests whether a given verification has status
-   * {@link VerificationStatus#REFUTED}.
-   *
-   * @return The predicate.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Predicate<Verification> isRefutedPredicate() {
-    return IS_REFUTED_PREDICATE;
-  }
-
-  private static final Predicate<Verification> IS_REFUTED_PREDICATE
-      = getStatusPredicate(VerificationStatus.REFUTED);
-
-  /**
-   * Gets a predicate that tests whether a verification is expired
-   *
-   * @param time The reference time for the expiration.
-   * @return The corresponding predicate.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Predicate<Verification> getExpirationPredicate(final long time) {
-    return new Predicate<Verification>() {
-      @Override
-      public boolean apply(Verification v) {
-        return v.hasExpired(time);
-      }
-    };
-  }
-
-  /**
-   * Gets a predicate that tests whether a verification should expire after the
-   * current request.
-   *
-   * @return The predicate.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Predicate<Verification> getRequestExpirationPredicate() {
-    return REQUEST_EXPIRATION_PREDICATE;
-  }
-
-  private static final Function<Verification, Long> GET_EXPIRATION_TIME_FUNCTION =
-      new Function<Verification, Long>() {
-        @Override
-        public Long apply(Verification v) {
-          return v.getExpirationTime();
-        }
-      };
-
-  private static final Predicate<Verification> REQUEST_EXPIRATION_PREDICATE =
-      Predicates.compose(Predicates.equalTo(EXPIRES_AFTER_REQUEST), GET_EXPIRATION_TIME_FUNCTION);
-
-  /**
-   * Gets a predicate that invokes the {@link #containsCredential} method on a
-   * given verification.
-   *
-   * @param credential The credential to test for.
-   * @return The corresponding predicate.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Predicate<Verification> getContainsCredentialPredicate(
-      final Credential credential) {
-    Preconditions.checkNotNull(credential);
-    return new Predicate<Verification>() {
-      @Override
-      public boolean apply(Verification verification) {
-        return verification.containsCredential(credential);
-      }
-    };
-  }
-
-  /**
-   * Gets a predicate that invokes the {@link #containsAllCredentials} method on
-   * a given verification.
-   *
-   * @param credentials The credentials to test for.
-   * @return The corresponding predicate.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Predicate<Verification> getContainsAllCredentialsPredicate(
-      final Iterable<? extends Credential> credentials) {
-    Preconditions.checkNotNull(credentials);
-    return new Predicate<Verification>() {
-      @Override
-      public boolean apply(Verification verification) {
-        return verification.containsAllCredentials(credentials);
-      }
-    };
-  }
-
-  /**
-   * Gets a predicate that invokes the {@link #containsAllCredentials} method on
-   * a given verification.
-   *
-   * @param credentials The credentials to test for.
-   * @return The corresponding predicate.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Predicate<Verification> getContainsAllCredentialsPredicate(
-      Credential... credentials) {
-    return getContainsAllCredentialsPredicate(Arrays.asList(credentials));
-  }
-
-  /**
-   * Gets a predicate that invokes the {@link #containsAnyCredential} method on
-   * a given verification.
-   *
-   * @param credentials The credentials to test for.
-   * @return The corresponding predicate.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Predicate<Verification> getContainsAnyCredentialPredicate(
-      final Iterable<? extends Credential> credentials) {
-    return new Predicate<Verification>() {
-      public boolean apply(Verification v) {
-        return v.containsAnyCredential(credentials);
-      }
-    };
-  }
-
-  /**
-   * Gets a predicate that invokes the {@link #containsAnyCredential} method on
-   * a given verification.
-   *
-   * @param credentials The credentials to test for.
-   * @return The corresponding predicate.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Predicate<Verification> getContainsAnyCredentialPredicate(
-      Credential... credentials) {
-    return getContainsAnyCredentialPredicate(Arrays.asList(credentials));
-  }
-
-  /**
-   * Determines the verification status from a set of verifications.
-   *
-   * @param verifications The set of verifications to check.
-   * @return The aggregate status of the verifications.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static VerificationStatus getStatus(Iterable<Verification> verifications) {
-    VerificationStatus result = VerificationStatus.INDETERMINATE;
-    for (Verification verification : verifications) {
-      if (verification.isRefuted()) {
-        return VerificationStatus.REFUTED;
-      }
-      if (verification.isVerified()) {
-        result = VerificationStatus.VERIFIED;
-      }
-    }
-    return result;
-  }
-
-  /**
-   * Determines the joint verification status for some given credentials from a
-   * set of verifications.
-   *
-   * @param verifications The set of verifications to check.
-   * @param credentials The set of credentials to look for.
-   * @return The joint verification status of the relevant verifications.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static VerificationStatus getStatus(Iterable<Verification> verifications,
-      Iterable<? extends Credential> credentials) {
-    return getStatus(
-        Iterables.filter(verifications,
-            getContainsAllCredentialsPredicate(credentials)));
-  }
-
-  /**
-   * Determines whether one of a set of verifications has VERIFIED state.
-   *
-   * @param verifications The set of verifications to check.
-   * @return True if there's at least one VERIFIED element in the set.
-   */
-  public static boolean isVerified(Iterable<Verification> verifications) {
-    return getStatus(verifications) == VerificationStatus.VERIFIED;
-  }
-
-  /**
-   * Determines whether one of a set of verifications has REFUTED state.
-   *
-   * @param verifications The set of verifications to check.
-   * @return True if there's at least one REFUTED element in the set.
-   */
-  public static boolean isRefuted(Iterable<Verification> verifications) {
-    return getStatus(verifications) == VerificationStatus.REFUTED;
-  }
-
-  /**
-   * Determines whether none of a set of verifications has VERIFIED or REFUTED
-   * state.
-   *
-   * @param verifications The set of verifications to check.
-   * @return False if there's at least one VERIFIED or REFUTED element in the
-   *     set.
-   */
-  public static boolean isIndeterminate(Iterable<Verification> verifications) {
-    return getStatus(verifications) == VerificationStatus.INDETERMINATE;
-  }
-
-  /**
-   * Determines whether one of a set of verifications has VERIFIED state and
-   * contains all of the given credentials.
-   *
-   * @param verifications The set of verifications to check.
-   * @param credentials The set of credentials to look for.
-   * @return True if there's at least one VERIFIED element in the containing all
-   *     of the credentials.
-   */
-  public static boolean isVerified(Iterable<Verification> verifications,
-      Iterable<Credential> credentials) {
-    return getStatus(verifications, credentials) == VerificationStatus.VERIFIED;
-  }
-
-  /**
-   * Determines whether one of a set of verifications has REFUTED state and
-   * contains all of the given credentials.
-   *
-   * @param verifications The set of verifications to check.
-   * @param credentials The set of credentials to look for.
-   * @return True if there's at least one REFUTED element in the containing all
-   *     of the credentials.
-   */
-  public static boolean isRefuted(Iterable<Verification> verifications,
-      Iterable<Credential> credentials) {
-    return getStatus(verifications, credentials) == VerificationStatus.REFUTED;
-  }
-
-  /**
-   * Gets the newest of a set of verifications; in other words, the verification
-   * with the latest expiration time.
-   *
-   * @param verifications The verifications to test.
-   * @return The newest of the given verifications, or {@code null} if the given
-   *     set is empty.
-   */
-  @CheckReturnValue
-  @Nonnull
-  public static Verification newestOf(Iterable<Verification> verifications) {
-    Verification result = null;
-    for (Verification verification : verifications) {
-      if (result == null || verification.compareExpirationTimes(result) > 0) {
-        result = verification;
-      }
-    }
-    return result;
-  }
-
-  /**
-   * Removes any expired verifications from a given collection.
-   *
-   * @param verifications A collection of verifications to process.
-   * @param timeStamp A reference time for determining expiration.
-   */
-  public static void expireVerifications(Collection<Verification> verifications,
-      @Nonnegative long timeStamp) {
-    Iterables.removeIf(verifications, getExpirationPredicate(timeStamp));
-  }
-
-  /**
-   * Removes any expired verifications from a given collection.  Uses the
-   * current time as a reference.
-   *
-   * @param verifications A collection of verifications to process.
-   */
-  public static void expireVerifications(Collection<Verification> verifications) {
-    expireVerifications(verifications, DateTimeUtils.currentTimeMillis());
-  }
-
-  static void registerTypeAdapters(GsonBuilder builder) {
-    builder.registerTypeAdapter(Verification.class,
-        ProxyTypeAdapter.make(Verification.class, LocalProxy.class));
-    builder.registerTypeAdapter(new TypeToken<ImmutableSet<Credential>>() {}.getType(),
-        TypeAdapters.immutableSet());
-  }
-
-  private static final class LocalProxy implements TypeProxy<Verification> {
-    VerificationStatus status;
-    long expirationTime;
-    ImmutableSet<Credential> credentials;
-
-    @SuppressWarnings("unused")
-    LocalProxy() {
-    }
-
-    @SuppressWarnings("unused")
-    LocalProxy(Verification verification) {
-      status = verification.getStatus();
-      expirationTime = verification.getExpirationTime();
-      credentials = verification.getCredentials();
-    }
-
-    @Override
-    public Verification build() {
-      return new Verification(status, expirationTime, credentials);
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/identity/VerificationStatus.java b/src/com/google/enterprise/secmgr/identity/VerificationStatus.java
deleted file mode 100644
index 4ddaf2c..0000000
--- a/src/com/google/enterprise/secmgr/identity/VerificationStatus.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.identity;
-
-/**
- * The status code attached to a {@link Verification} indicating the disposition
- * of the verification.
- */
-public enum VerificationStatus {
-  VERIFIED,       // recognized by IdP
-  REFUTED,        // unrecognized by IdP
-  INDETERMINATE   // unable to verify
-}
diff --git a/src/com/google/enterprise/secmgr/modules/SamlClient.java b/src/com/google/enterprise/secmgr/modules/SamlClient.java
index 85ebae5..28880e2 100644
--- a/src/com/google/enterprise/secmgr/modules/SamlClient.java
+++ b/src/com/google/enterprise/secmgr/modules/SamlClient.java
@@ -14,7 +14,6 @@
 
 package com.google.enterprise.secmgr.modules;
 
-import static com.google.enterprise.secmgr.saml.OpenSamlUtil.getMetadataSignaturePolicyRule;
 import static com.google.enterprise.secmgr.saml.OpenSamlUtil.initializeLocalEntity;
 import static com.google.enterprise.secmgr.saml.OpenSamlUtil.initializePeerEntity;
 import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeAction;
@@ -22,9 +21,7 @@
 import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeAuthnRequest;
 import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeAuthzDecisionQuery;
 import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeSamlMessageContext;
-import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeStaticSecurityPolicyResolver;
 import static com.google.enterprise.secmgr.saml.OpenSamlUtil.makeSubject;
-import static com.google.enterprise.secmgr.saml.OpenSamlUtil.peerSupportsSignatureVerification;
 import static com.google.enterprise.secmgr.saml.OpenSamlUtil.runDecoder;
 import static com.google.enterprise.secmgr.saml.OpenSamlUtil.runEncoder;
 import static org.opensaml.common.xml.SAMLConstants.SAML20P_NS;
@@ -33,24 +30,19 @@
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
-//import com.google.enterprise.secmgr.authncontroller.AuthnSession;
 import com.google.enterprise.secmgr.common.AuthzStatus;
-import com.google.enterprise.secmgr.common.HttpUtil;
-//import com.google.enterprise.secmgr.common.ServletBase;
 import com.google.enterprise.secmgr.http.HttpClientInterface;
 import com.google.enterprise.secmgr.http.HttpExchange;
 import com.google.enterprise.secmgr.saml.HTTPSOAP11MultiContextDecoder;
 import com.google.enterprise.secmgr.saml.HTTPSOAP11MultiContextEncoder;
 import com.google.enterprise.secmgr.saml.HttpExchangeToInTransport;
 import com.google.enterprise.secmgr.saml.HttpExchangeToOutTransport;
-import com.google.enterprise.secmgr.saml.MetadataEditor;
 import com.google.enterprise.secmgr.saml.SamlLogUtil;
 
 import org.joda.time.DateTime;
 import org.opensaml.common.SAMLObject;
 import org.opensaml.common.binding.SAMLMessageContext;
 import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.binding.decoding.HTTPPostDecoder;
 import org.opensaml.saml2.binding.decoding.HTTPSOAP11Decoder;
 import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder;
 import org.opensaml.saml2.binding.encoding.HTTPSOAP11Encoder;
@@ -75,16 +67,13 @@
 import org.opensaml.util.URLBuilder;
 import org.opensaml.ws.message.encoder.MessageEncoder;
 import org.opensaml.ws.message.encoder.MessageEncodingException;
-import org.opensaml.ws.security.provider.MandatoryAuthenticatedMessageRule;
-import org.opensaml.ws.security.provider.MandatoryIssuerRule;
 import org.opensaml.ws.transport.http.HTTPInTransport;
 import org.opensaml.ws.transport.http.HTTPOutTransport;
-import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
-import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
 import org.opensaml.xml.security.credential.Credential;
 import org.opensaml.xml.util.Pair;
 
 import java.io.IOException;
+import java.net.HttpURLConnection;
 import java.net.URI;
 import java.net.URL;
 import java.util.Collection;
@@ -94,8 +83,6 @@
 
 import javax.annotation.concurrent.GuardedBy;
 import javax.annotation.concurrent.ThreadSafe;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 
 /**
  * A library implementing most of the functionality of a SAML service provider.
@@ -200,7 +187,7 @@
    * @return The assertion consumer service descriptor.
    */
   public AssertionConsumerService getPostAssertionConsumerService() {
-    return getAssertionConsumerService(MetadataEditor.SAML_BINDING_HTTP_POST);
+    return getAssertionConsumerService(SAMLConstants.SAML2_POST_BINDING_URI);
   }
 
   /**
@@ -209,7 +196,7 @@
    * @return The assertion consumer service descriptor.
    */
   public AssertionConsumerService getArtifactAssertionConsumerService() {
-    return getAssertionConsumerService(MetadataEditor.SAML_BINDING_HTTP_ARTIFACT);
+    return getAssertionConsumerService(SAMLConstants.SAML2_ARTIFACT_BINDING_URI);
   }
 
   private AssertionConsumerService getAssertionConsumerService(String binding) {
@@ -269,56 +256,6 @@
   }
 
   /**
-   * Decode a SAML response sent via the POST binding.
-   *
-   * @param request The HTTP request containing the encoded response.
-   * @return The decoded response, or null if there was an error decoding the message.  In
-   *     this case, a log file entry is generated, so the caller doesn't need to know the
-   *     details of the failure.
-   * @throws IOException for various errors related to session and metadata.
-   */
-  /*
-  // Commented out to prevent pulling in AuthnSession.
-  public Response decodePostResponse(HttpServletRequest request)
-      throws IOException {
-    AuthnSession session = AuthnSession.getInstance(request);
-    if (session == null) {
-      return null;
-    }
-    SAMLMessageContext<Response, SAMLObject, NameID> context =
-        makeSamlMessageContext();
-
-    initializeLocalEntity(context, localEntity, localEntity.getSPSSODescriptor(SAML20P_NS));
-    initializePeerEntity(context, peerEntity, peerEntity.getIDPSSODescriptor(SAML20P_NS),
-        SingleSignOnService.DEFAULT_ELEMENT_NAME,
-        SAML2_REDIRECT_BINDING_URI);
-
-    if (!peerSupportsSignatureVerification(context)) {
-      LOGGER.warning("SAML POST peer not configured for signature verification");
-      return null;
-    }
-
-    // Create a security policy to check the response signature.  Works only
-    // with certificates that are stored in the metadata.
-    context.setSecurityPolicyResolver(
-        makeStaticSecurityPolicyResolver(
-            getMetadataSignaturePolicyRule(request),
-            // Requires an <Issuer>:
-            new MandatoryIssuerRule(),
-            // Requires that the message be authenticated:
-            new MandatoryAuthenticatedMessageRule()));
-
-    context.setInboundMessageTransport(new HttpServletRequestAdapter(request));
-    if (!runDecoder(new HTTPPostDecoder(), context, session, "client identity provider")) {
-      return null;
-    }
-
-    Response samlResponse = context.getInboundSAMLMessage();
-    Preconditions.checkNotNull(samlResponse, "Decoded SAML response is null");
-    return samlResponse;
-  }*/
-
-  /**
    * Decode a SAML response sent via the artifact binding.
    *
    * @param request The HTTP request containing the artifact.
@@ -405,7 +342,7 @@
 
     // Do HTTP exchange.
     int status = exchange.exchange();
-    if (status != HttpServletResponse.SC_OK) {
+    if (status != HttpURLConnection.HTTP_OK) {
       LOGGER.warning("Incorrect HTTP status: " + status);
       return null;
     }
@@ -448,7 +385,7 @@
 
       // Do HTTP exchange
       int status = exchange.exchange();
-      if (!HttpUtil.isGoodHttpStatus(status)) {
+      if (!isGoodHttpStatus(status)) {
         throw new IOException("Incorrect HTTP status: " + status);
       }
 
@@ -511,7 +448,7 @@
 
       // Do HTTP exchange
       int status = exchange.exchange();
-      if (!HttpUtil.isGoodHttpStatus(status)) {
+      if (!isGoodHttpStatus(status)) {
         throw new IOException("Incorrect HTTP status: " + status);
       }
 
@@ -678,4 +615,9 @@
       return builder.buildURL();
     }
   }
+
+  public static boolean isGoodHttpStatus(int status) {
+    return status == HttpURLConnection.HTTP_OK
+        || status == HttpURLConnection.HTTP_PARTIAL;
+  }
 }
diff --git a/src/com/google/enterprise/secmgr/saml/HTTPSOAP11MultiContextDecoder.java b/src/com/google/enterprise/secmgr/saml/HTTPSOAP11MultiContextDecoder.java
index b997127..5021b89 100644
--- a/src/com/google/enterprise/secmgr/saml/HTTPSOAP11MultiContextDecoder.java
+++ b/src/com/google/enterprise/secmgr/saml/HTTPSOAP11MultiContextDecoder.java
@@ -27,11 +27,11 @@
 import org.opensaml.xml.XMLObject;
 import org.opensaml.xml.parse.ParserPool;
 import org.opensaml.xml.util.DatatypeHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import javax.xml.namespace.QName;
 
@@ -42,7 +42,7 @@
 public class HTTPSOAP11MultiContextDecoder extends BaseSAML2MessageDecoder {
 
   /** Class logger. */
-  private final Logger log = LoggerFactory.getLogger(HTTPSOAP11MultiContextDecoder.class);
+  private static final Logger log = Logger.getLogger(HTTPSOAP11MultiContextDecoder.class.getName());
 
   /** QNames of understood SOAP headers. */
   private final List<QName> understoodHeaders = new ArrayList<QName>();
@@ -102,7 +102,6 @@
   @Override
   protected void doDecode(MessageContext messageContext) throws MessageDecodingException {
     if (!(messageContext instanceof SAMLMessageContext<?, ?, ?>)) {
-      log.error("Invalid message context type, this decoder only support SAMLMessageContext");
       throw new MessageDecodingException(
           "Invalid message context type, this decoder only support SAMLMessageContext");
     }
@@ -116,10 +115,9 @@
     }
 
     if (soapBodyChildren.size() < 1) {
-      log.error("Unexpected number of children in the SOAP body, " + soapBodyChildren.size()
-          + ".  Unable to extract SAML message");
       throw new MessageDecodingException(
-          "Unexpected number of children in the SOAP body, unable to extract SAML message");
+          "Unexpected number of children in the SOAP body, " + soapBodyChildren.size()
+          + ". Unable to extract SAML message");
     }
 
     if (thisChild >= soapBodyChildren.size()) {
@@ -132,16 +130,15 @@
     thisChild++;
 
     if (!(incomingMessage instanceof SAMLObject)) {
-      log.error("Unexpected SOAP body content.  Expected a SAML request but recieved {}",
-          incomingMessage.getElementQName());
       throw new MessageDecodingException(
           "Unexpected SOAP body content.  Expected a SAML request but recieved "
               + incomingMessage.getElementQName());
     }
     SAMLObject samlMessage = (SAMLObject) incomingMessage;
 
-    log.debug("Decoded SOAP messaged which included SAML message of type {}",
-              samlMessage.getElementQName());
+    log.log(Level.FINE,
+        "Decoded SOAP messaged which included SAML message of type {}",
+        samlMessage.getElementQName());
     samlMsgCtx.setInboundSAMLMessage(samlMessage);
 
     populateMessageContext(samlMsgCtx);
@@ -183,8 +180,6 @@
   private void start(SAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> samlMsgCtx)
       throws MessageDecodingException {
     if (!(samlMsgCtx.getInboundMessageTransport() instanceof HTTPInTransport)) {
-      log.error(
-          "Invalid inbound message transport type, this decoder only support HTTPInTransport");
       throw new MessageDecodingException(
           "Invalid inbound message transport type, this decoder only support HTTPInTransport");
     }
@@ -195,7 +190,7 @@
           "This message deocoder only supports the HTTP POST method");
     }
 
-    log.debug("Unmarshalling SOAP message");
+    log.fine("Unmarshalling SOAP message");
     soapMessage = Envelope.class.cast(unmarshallMessage(inTransport.getIncomingStream()));
 
     Header messageHeader = soapMessage.getHeader();
diff --git a/src/com/google/enterprise/secmgr/saml/HTTPSOAP11MultiContextEncoder.java b/src/com/google/enterprise/secmgr/saml/HTTPSOAP11MultiContextEncoder.java
index f982483..0794408 100644
--- a/src/com/google/enterprise/secmgr/saml/HTTPSOAP11MultiContextEncoder.java
+++ b/src/com/google/enterprise/secmgr/saml/HTTPSOAP11MultiContextEncoder.java
@@ -28,14 +28,13 @@
 import org.opensaml.ws.transport.http.HTTPTransportUtils;
 import org.opensaml.xml.XMLObjectBuilderFactory;
 import org.opensaml.xml.util.XMLHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.w3c.dom.Element;
 
 import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.io.UnsupportedEncodingException;
 import java.io.Writer;
+import java.util.logging.Logger;
 
 /**
  * SAML 2.0 SOAP 1.1 over HTTP MultiContext binding encoder.
@@ -48,7 +47,7 @@
   private HTTPOutTransport outTransport;
 
   /** Class logger. */
-  private final Logger log = LoggerFactory.getLogger(HTTPSOAP11MultiContextEncoder.class);
+  private static final Logger log = Logger.getLogger(HTTPSOAP11MultiContextEncoder.class.getName());
 
   /** Constructor. */
   public HTTPSOAP11MultiContextEncoder() {
@@ -78,7 +77,6 @@
   @Override
   protected void doEncode(MessageContext messageContext) throws MessageEncodingException {
     if (!(messageContext instanceof SAMLMessageContext<?, ?, ?>)) {
-      log.error("Invalid message context type, this encoder only supports SAMLMessageContext");
       throw new MessageEncodingException(
           "Invalid message context type, this encoder only supports SAMLMessageContext");
     }
@@ -87,8 +85,6 @@
         (SAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>) messageContext;
 
     if (!(messageContext.getOutboundMessageTransport() instanceof HTTPOutTransport)) {
-      log.error(
-          "Invalid outbound message transport type, this encoder only supports HTTPOutTransport");
       throw new MessageEncodingException(
           "Invalid outbound message transport type, this encoder only supports HTTPOutTransport");
     }
@@ -106,9 +102,7 @@
     signMessage(samlMsgCtx);
     samlMsgCtx.setOutboundMessage(envelope);
 
-    if (log.isDebugEnabled()) {
-      log.debug("Adding SAML message to the SOAP message's body");
-    }
+    log.fine("Adding SAML message to the SOAP message's body");
 
     body.getUnknownXMLObjects().add(samlMessage);
   }
@@ -124,10 +118,8 @@
       XMLHelper.writeNode(envelopeElem, out);
       out.flush();
     } catch (UnsupportedEncodingException e) {
-      log.error("JVM does not support required UTF-8 encoding");
       throw new MessageEncodingException("JVM does not support required UTF-8 encoding");
     } catch (IOException e) {
-      log.error("Unable to write message content to outbound stream", e);
       throw new MessageEncodingException("Unable to write message content to outbound stream", e);
     }
   }
@@ -136,9 +128,7 @@
    * Builds the SOAP message to be encoded.
    */
   protected void buildSOAPMessage() {
-    if (log.isDebugEnabled()) {
-      log.debug("Building SOAP message");
-    }
+    log.fine("Building SOAP message");
     XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
 
     @SuppressWarnings("unchecked")
diff --git a/src/com/google/enterprise/secmgr/saml/Metadata.java b/src/com/google/enterprise/secmgr/saml/Metadata.java
deleted file mode 100644
index df06562..0000000
--- a/src/com/google/enterprise/secmgr/saml/Metadata.java
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright 2008 Google Inc.
-//
-// 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.secmgr.saml;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Maps;
-import com.google.enterprise.secmgr.common.FileUtil;
-import com.google.enterprise.secmgr.common.SecurityManagerUtil;
-import com.google.enterprise.secmgr.common.XmlUtil;
-import com.google.enterprise.secmgr.config.ConfigSingleton;
-
-import org.opensaml.saml2.metadata.EntitiesDescriptor;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.provider.AbstractObservableMetadataProvider;
-import org.opensaml.saml2.metadata.provider.MetadataProvider;
-import org.opensaml.saml2.metadata.provider.MetadataProviderException;
-import org.opensaml.saml2.metadata.provider.ObservableMetadataProvider;
-import org.opensaml.xml.XMLObject;
-import org.opensaml.xml.io.MarshallingException;
-import org.opensaml.xml.io.UnmarshallingException;
-import org.w3c.dom.CDATASection;
-import org.w3c.dom.Comment;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.EntityReference;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.ProcessingInstruction;
-import org.w3c.dom.Text;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Map;
-import java.util.logging.Logger;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.annotation.concurrent.ThreadSafe;
-
-/**
- * An abstract interface to the SAML metadata configuration.  Tracks a given
- * metadata file and keeps it up to date.  Also rewrites the metadata so it uses
- * the correct hostname.
- */
-@ThreadSafe
-public class Metadata {
-
-  private static final Logger LOGGER = Logger.getLogger(Metadata.class.getName());
-
-  @GuardedBy("itself")
-  private static final Map<String, Metadata> perHostMap = Maps.newHashMap();
-  private static File metadataFile = null;
-
-  private final MetadataProvider provider;
-
-  private Metadata(String urlPrefix)
-      throws IOException {
-    try {
-      this.provider = new MyProvider(
-          OpenSamlUtil.getMetadataFromFile(
-              (metadataFile != null)
-              ? metadataFile
-              : FileUtil.getContextFile(ConfigSingleton.getSamlMetadataFilename())),
-          urlPrefix, SecurityManagerUtil.getGsaEntConfigName());
-    } catch (MetadataProviderException e) {
-      throw new IOException(e);
-    }
-  }
-
-  @VisibleForTesting
-  static void setMetadataFile(File metadataFile) {
-    Metadata.metadataFile = metadataFile;
-  }
-
-  @VisibleForTesting
-  public static Metadata getInstance(String host)
-      throws IOException {
-    return getInstance("http", host);
-  }
-
-  public static Metadata getInstance(URL url)
-      throws IOException {
-    return getInstance(url.getProtocol(), url.getHost());
-  }
-
-  public static Metadata getInstance(String protocol, String host)
-      throws IOException {
-    String urlPrefix = protocol + "://" + host;
-    Metadata result;
-    synchronized (perHostMap) {
-      result = perHostMap.get(urlPrefix);
-      if (result == null) {
-        result = new Metadata(urlPrefix);
-        perHostMap.put(urlPrefix, result);
-      }
-    }
-    return result;
-  }
-
-  public MetadataProvider getProvider() {
-    return provider;
-  }
-
-  public EntitiesDescriptor getMetadata() throws IOException {
-    XMLObject root;
-    try {
-      root = provider.getMetadata();
-    } catch (MetadataProviderException e) {
-      throw new IOException(e);
-    }
-    if (root instanceof EntitiesDescriptor) {
-      return (EntitiesDescriptor) root;
-    }
-    throw new IOException("Malformed SAML metadata");
-  }
-
-  public EntityDescriptor getEntity(String id) throws IOException {
-    EntityDescriptor entity;
-    try {
-      entity = provider.getEntityDescriptor(id);
-    } catch (MetadataProviderException e) {
-      throw new IOException(e);
-    }
-    if (entity == null) {
-      throw new IllegalArgumentException("Unknown entity ID: " + id);
-    }
-    return entity;
-  }
-
-  public EntityDescriptor getSmEntity() throws IOException {
-    for (EntityDescriptor e : getMetadata().getEntityDescriptors()) {
-      if (MetadataEditor.SECMGR_ID_FOR_ENTITY.equals(e.getID())) {
-        return e;
-      }
-    }
-    throw new IllegalStateException("Can't find security manager's entity descriptor");
-  }
-
-  public String getSmEntityId() throws IOException {
-    return getSmEntity().getEntityID();
-  }
-
-  /**
-   * This class implements a wrapper around an OpenSAML
-   * ObservableMetadataProvider that customizes the metadata for a particular
-   * host.  When the metadata is updated, as when the configuration file is
-   * changed, this provider notices that, gets the updated metadata, and
-   * customizes it.  To speed things up a bit, the customized metadata is
-   * cached, so it need not be customized every time.
-   */
-  private static class MyProvider
-      extends AbstractObservableMetadataProvider
-      implements ObservableMetadataProvider.Observer {
-
-    private final ObservableMetadataProvider wrappedProvider;
-    private final String urlPrefix;
-    private final String gsaEntConfigName;
-    private XMLObject savedMetadata;
-
-    public MyProvider(ObservableMetadataProvider wrappedProvider,
-        String urlPrefix, String gsaEntConfigName) {
-      super();
-      this.wrappedProvider = wrappedProvider;
-      this.urlPrefix = urlPrefix;
-      this.gsaEntConfigName = gsaEntConfigName;
-      savedMetadata = null;
-      wrappedProvider.getObservers().add(this);
-    }
-
-    public synchronized void onEvent(MetadataProvider provider) {
-      LOGGER.info("Clearing cached metadata");
-      savedMetadata = null;
-      emitChangeEvent();
-    }
-
-    public synchronized XMLObject getMetadata() throws MetadataProviderException {
-      // This will call onEvent if the file has changed:
-      XMLObject rawMetadata = wrappedProvider.getMetadata();
-      if (savedMetadata == null) {
-        try {
-          savedMetadata = OpenSamlUtil.unmarshallXmlObject(
-              substituteTopLevel(
-                  OpenSamlUtil.marshallXmlObject(rawMetadata)));
-        } catch (MarshallingException e) {
-          throw new MetadataProviderException(e);
-        } catch (UnmarshallingException e) {
-          throw new MetadataProviderException(e);
-        }
-      }
-      return savedMetadata;
-    }
-
-    private Element substituteTopLevel(Element element) {
-      Document doc = XmlUtil.getInstance()
-          .makeDocument(element.getNamespaceURI(), element.getTagName(), null);
-      Element newElement = doc.getDocumentElement();
-      substituteInNodeChildren(element, newElement, doc);
-      return newElement;
-    }
-
-    private void substituteInNodeChildren(Node node, Node newNode, Document doc) {
-      if (node instanceof Element) {
-        NamedNodeMap attrs = node.getAttributes();
-        NamedNodeMap newAttrs = newNode.getAttributes();
-        for (int i = 0; i < attrs.getLength(); i++) {
-          Node attr = attrs.item(i);
-          Node newAttr = doc.createAttributeNS(attr.getNamespaceURI(), attr.getNodeName());
-          newAttr.setNodeValue(substituteInString(attr.getNodeValue()));
-          newAttrs.setNamedItemNS(newAttr);
-        }
-      }
-      for (Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
-        Node newChild = substituteInNode(child, doc);
-        substituteInNodeChildren(child, newChild, doc);
-        newNode.appendChild(newChild);
-      }
-    }
-
-    private Node substituteInNode(Node node, Document doc) {
-      if (node instanceof Element) {
-        return doc.createElementNS(node.getNamespaceURI(), node.getNodeName());
-      } else if (node instanceof Text) {
-        return doc.createTextNode(substituteInString(node.getNodeValue()));
-      } else if (node instanceof CDATASection) {
-        return doc.createCDATASection(node.getNodeValue());
-      } else if (node instanceof Comment) {
-        return doc.createComment(node.getNodeValue());
-      } else if (node instanceof EntityReference) {
-        return doc.createEntityReference(node.getNodeName());
-      } else if (node instanceof ProcessingInstruction) {
-        return doc.createProcessingInstruction(node.getNodeName(), node.getNodeValue());
-      } else {
-        throw new IllegalArgumentException("Unknown node type: " + node.getNodeType());
-      }
-    }
-
-    private String substituteInString(String original) {
-      if (original == null) { return original; }
-      String pattern = "https://" + MetadataEditor.GSA_HOST_MARKER;
-      if (original.startsWith(pattern)) {
-        return original.replace(pattern, urlPrefix);
-      }
-      pattern = "http://" + MetadataEditor.GSA_HOST_MARKER;
-      if (original.startsWith(pattern)) {
-        return original.replace(pattern, urlPrefix);
-      }
-      if (original.contains(MetadataEditor.GSA_ENT_CONFIG_NAME_MARKER)) {
-        return original.replace(MetadataEditor.GSA_ENT_CONFIG_NAME_MARKER, gsaEntConfigName);
-      }
-      return original;
-    }
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/saml/MetadataEditor.java b/src/com/google/enterprise/secmgr/saml/MetadataEditor.java
deleted file mode 100644
index 933ed08..0000000
--- a/src/com/google/enterprise/secmgr/saml/MetadataEditor.java
+++ /dev/null
@@ -1,1069 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// 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.secmgr.saml;
-
-import static com.google.enterprise.secmgr.common.XmlUtil.countChildElements;
-import static com.google.enterprise.secmgr.common.XmlUtil.findChildComments;
-import static com.google.enterprise.secmgr.common.XmlUtil.findChildElement;
-import static com.google.enterprise.secmgr.common.XmlUtil.getElementsByQname;
-import static com.google.enterprise.secmgr.common.XmlUtil.makeCommentChild;
-import static com.google.enterprise.secmgr.common.XmlUtil.makeElement;
-import static com.google.enterprise.secmgr.common.XmlUtil.makeElementChild;
-import static com.google.enterprise.secmgr.common.XmlUtil.makeTextChild;
-import static com.google.enterprise.secmgr.common.XmlUtil.makeTextElementChild;
-import static com.google.enterprise.secmgr.common.XmlUtil.setConfigParams;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import com.google.enterprise.secmgr.common.XmlUtil;
-
-import org.w3c.dom.Comment;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.Writer;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.annotation.concurrent.Immutable;
-import javax.xml.crypto.dsig.XMLSignature;
-import javax.xml.namespace.QName;
-
-/**
- * Utilities for editing SAML metadata files.
- */
-@Immutable
-public class MetadataEditor {
-  private static final Logger LOGGER = Logger.getLogger(MetadataEditor.class.getName());
-
-  // SAML metadata elements.
-  public static final String SAML_MD_NS = "urn:oasis:names:tc:SAML:2.0:metadata";
-
-  private static QName mdName(String localPart) {
-    return new QName(SAML_MD_NS, localPart);
-  }
-
-  public static final QName SAML_DESCRIPTOR_ENTITIES = mdName("EntitiesDescriptor");
-  public static final QName SAML_DESCRIPTOR_ENTITY = mdName("EntityDescriptor");
-  public static final QName SAML_DESCRIPTOR_IDP_SSO = mdName("IDPSSODescriptor");
-  public static final QName SAML_DESCRIPTOR_KEY = mdName("KeyDescriptor");
-  public static final QName SAML_DESCRIPTOR_PDP = mdName("PDPDescriptor");
-  public static final QName SAML_DESCRIPTOR_SP_SSO = mdName("SPSSODescriptor");
-  public static final QName SAML_ORGANIZATION = mdName("Organization");
-  public static final QName SAML_ORGANIZATION_DISPLAY_NAME = mdName("OrganizationDisplayName");
-  public static final QName SAML_ORGANIZATION_NAME = mdName("OrganizationName");
-  public static final QName SAML_ORGANIZATION_URL = mdName("OrganizationURL");
-  public static final QName SAML_SERVICE_ARTIFACT_RESOLUTION = mdName("ArtifactResolutionService");
-  public static final QName SAML_SERVICE_ASSERTION_CONSUMER = mdName("AssertionConsumerService");
-  public static final QName SAML_SERVICE_AUTHZ = mdName("AuthzService");
-  public static final QName SAML_SERVICE_SINGLE_SIGN_ON = mdName("SingleSignOnService");
-
-  // SAML metadata attributes.
-  public static final String SAML_ATTR_BINDING = "Binding";
-  public static final String SAML_ATTR_CACHE_DURATION = "cacheDuration";
-  public static final String SAML_ATTR_ENTITY_ID = "entityID";
-  public static final String SAML_ATTR_INDEX = "index";
-  public static final String SAML_ATTR_IS_DEFAULT = "isDefault";
-  public static final String SAML_ATTR_LOCATION = "Location";
-  public static final String SAML_ATTR_NAME = "Name";
-  public static final String SAML_ATTR_PROTOCOL_SUPPORT_ENUMERATION = "protocolSupportEnumeration";
-  public static final String SAML_ATTR_USE = "use";
-  public static final String XML_ATTR_ID = "ID";
-
-  // SAML metadata attribute values.
-  public static final String SAML_BINDING_HTTP_ARTIFACT =
-      "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact";
-  public static final String SAML_BINDING_HTTP_POST =
-      "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST";
-  public static final String SAML_BINDING_HTTP_REDIRECT =
-      "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect";
-  public static final String SAML_BINDING_SOAP = "urn:oasis:names:tc:SAML:2.0:bindings:SOAP";
-  public static final String SAML_PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol";
-  public static final String SAML_USAGE_SIGNING = "signing";
-  private static final String SAML_CACHE_DURATION = "PT1H";  // one hour
-
-  // Entity group for SAML clients.
-  public static final String SECMGR_CLIENTS_ENTITIES_NAME = "security-manager-clients";
-  public static final String SECMGR_CLIENTS_ENTITIES_COMMENT = "SAML client IdPs";
-
-  // XML Digital Signature elements.
-  private static QName dsName(String localPart) {
-    return new QName(XMLSignature.XMLNS, localPart, "ds");
-  }
-
-  public static final QName XMLDSIG_KEY_INFO = dsName("KeyInfo");
-  public static final QName XMLDSIG_X509_DATA = dsName("X509Data");
-  public static final QName XMLDSIG_X509_CERTIFICATE = dsName("X509Certificate");
-
-  // Entity for GSA.
-  public static final String GSA_ENTITY_ID_ROOT = "http://google.com/enterprise/gsa/";
-  public static final String GSA_ENTITY_COMMENT = "Description of the GSA";
-  public static final String GSA_ENT_CONFIG_NAME_MARKER = "${ENT_CONFIG_NAME}";
-
-  // Entity for security manager.
-  public static final String SECMGR_ENTITY_ID_SUFFIX = "/security-manager";
-  public static final String SECMGR_ENTITY_COMMENT = "Description of the Security Manager";
-  static final String SECMGR_ID_FOR_ENTITY = "security-manager";
-
-  // Google organization element.
-  public static final String GOOGLE_ORGANIZATION_NAME = "google.com";
-  public static final String GOOGLE_ORGANIZATION_DISPLAY_NAME = "Google Inc.";
-  public static final String GOOGLE_ORGANIZATION_URL = "http://www.google.com/";
-
-  // Endpoint URLs.
-  private static final String HTTP_PROTOCOL = "http";
-  private static final String HTTPS_PROTOCOL = "https";
-  static final String GSA_HOST_MARKER = "$$GSA$$";
-  private static final String SECMGR_WEBAPP_PATH = "/security-manager";
-  private static final String LOCALHOST = "localhost";
-
-  public static final String GSA_ASSERTION_CONSUMER_PATH = "SamlArtifactConsumer";
-
-  public static final String SECMGR_SSO_PATH = "samlauthn";
-  public static final String SECMGR_ARTIFACT_RESOLVER_PATH = "samlartifact";
-  public static final String SECMGR_ASSERTION_CONSUMER_PATH = "samlassertionconsumer";
-  public static final String SECMGR_AUTHZ_PATH = "samlauthz";
-  public static final String X509_HEADER = "-----BEGIN CERTIFICATE-----";
-  public static final String X509_FOOTER = "-----END CERTIFICATE-----";
-
-  // Don't instantiate this class.
-  private MetadataEditor() {}
-
-  /**
-   * A datatype to hold the parameters of a SAML client IdP.
-   */
-  @Immutable
-  public static class SamlClientIdp {
-
-    private final String id;
-    private final String loginUrl;
-    private final String artifactUrl;
-    private final String certificate;
-    private final String authzServiceUrl;
-
-    private SamlClientIdp(String id, String loginUrl, String artifactUrl, String certificate,
-        String authzServiceUrl) {
-      Preconditions.checkNotNull(id);
-      this.id = id;
-      this.loginUrl = loginUrl;
-      this.artifactUrl = artifactUrl;
-      this.certificate = normalizeCertificate(certificate);
-      this.authzServiceUrl = authzServiceUrl;
-    }
-
-    /**
-     * Make a client with only IDP SSO components.
-     *
-     * @param id The entity ID for the IdP.
-     * @param loginUrl The single sign-on service URL for the IdP.
-     * @param artifactUrl The artifact resolution service URL for the IdP, or null if none.
-     * @param certificate A PEM encoded X509 certificate, or null if none.
-     * @return A new IDP SSO client.
-     */
-    public static SamlClientIdp makeSso(String id, String loginUrl, String artifactUrl,
-        String certificate) {
-      Preconditions.checkNotNull(loginUrl);
-      Preconditions.checkArgument(artifactUrl != null ^ certificate != null);
-      return new SamlClientIdp(id, loginUrl, artifactUrl, certificate, null);
-    }
-
-    /**
-     * Make a client with only PDP components.
-     *
-     * @param id The entity ID for the PDP.
-     * @param authzServiceUrl The URL for the PDP's AuthzService.
-     * @return A new PDP client.
-     */
-    public static SamlClientIdp makePdp(String id, String authzServiceUrl) {
-      Preconditions.checkNotNull(authzServiceUrl);
-      return new SamlClientIdp(id, null, null, null, authzServiceUrl);
-    }
-
-    /**
-     * @return True if this client has IdP SSO components.
-     */
-    public boolean hasSso() {
-      return loginUrl != null && (artifactUrl != null || certificate != null);
-    }
-
-    /**
-     * @return True if this client has PDP components.
-     */
-    public boolean hasPdp() {
-      return authzServiceUrl != null;
-    }
-
-    /**
-     * @return True if this client has components other than IDP SSO.
-     */
-    public boolean hasNonSso() {
-      return hasPdp();
-    }
-
-    /**
-     * @return True if this client has components other than PDP.
-     */
-    public boolean hasNonPdp() {
-      return hasSso();
-    }
-
-    /**
-     * Replace the IDP SSO components of this client with those of another.
-     *
-     * @param client The client to get the IDP SSO components from.
-     * @return A copy of this client with its IDP SSO components replaced.
-     */
-    public SamlClientIdp replaceSso(SamlClientIdp client) {
-      return new SamlClientIdp(id,
-          client.getUrl(),
-          client.getArtifactUrl(),
-          client.getCertificate(),
-          authzServiceUrl);
-    }
-
-    /**
-     * @return A copy of this client with its IDP SSO components removed.
-     */
-    public SamlClientIdp removeSso() {
-      return new SamlClientIdp(id, null, null, null, authzServiceUrl);
-    }
-
-    /**
-     * Replace the PDP components of this client with those of another.
-     *
-     * @param client The client to get the PDP components from.
-     * @return A copy of this client with its PDP components replaced.
-     */
-    public SamlClientIdp replacePdp(SamlClientIdp client) {
-      return new SamlClientIdp(id,
-          loginUrl,
-          artifactUrl,
-          certificate,
-          client.getAuthzServiceUrl());
-    }
-
-    /**
-     * @return A copy of this client with its PDP components removed.
-     */
-    public SamlClientIdp removePdp() {
-      return new SamlClientIdp(id, loginUrl, artifactUrl, certificate, null);
-    }
-
-    /**
-     * @return The entity ID of the SAML client.
-     */
-    public String getId() {
-      return id;
-    }
-
-    /**
-     * @return The single-sign-on entry URL for the SAML client.
-     */
-    public String getUrl() {
-      return loginUrl;
-    }
-
-    /**
-     * @return The artifact-resolution entry URL for the SAML client, or null if none.
-     */
-    public String getArtifactUrl() {
-      return artifactUrl;
-    }
-
-    /**
-     * @return The signing certificate for the SAML client, or null if none.
-     */
-    public String getCertificate() {
-      return certificate;
-    }
-
-    /**
-     * @return The AuthzService URL for the SAML client.
-     */
-    public String getAuthzServiceUrl() {
-      return authzServiceUrl;
-    }
-
-    @Override
-    public int hashCode() {
-      return Objects.hashCode(id, loginUrl, artifactUrl, certificate, authzServiceUrl);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-      if (obj == this) { return true; }
-      if (!(obj instanceof SamlClientIdp)) { return false; }
-      SamlClientIdp other = (SamlClientIdp) obj;
-      return Objects.equal(id, other.id)
-          && Objects.equal(loginUrl, other.loginUrl)
-          && Objects.equal(artifactUrl, other.artifactUrl)
-          && Objects.equal(certificate, other.certificate)
-          && Objects.equal(authzServiceUrl, other.authzServiceUrl);
-    }
-  }
-
-  /**
-   * Get the SAML client IdPs from metadata.
-   *
-   * @param document The metadata as a {@link Document}.
-   * @return A list of SAML client IdP descriptors.
-   * @throws IllegalArgumentException if metadata can't be parsed.
-   */
-  public static List<SamlClientIdp> getSamlClientsInMetadata(Document document) {
-    List<SamlClientIdp> clients = Lists.newArrayList();
-    Set<String> idsSeen = Sets.newHashSet();
-    Element entities = getSamlClients(document);
-    if (entities != null) {
-      NodeList nodes = getElementsByQname(entities, SAML_DESCRIPTOR_ENTITY);
-      for (int index = 0; index < nodes.getLength(); index++) {
-        Element element = Element.class.cast(nodes.item(index));
-        SamlClientIdp client;
-        try {
-          client = parseClient(element, idsSeen);
-        } catch (IllegalArgumentException e) {
-          LOGGER.log(Level.WARNING, "Unable to parse SAML client spec: ", e);
-          client = null;
-        }
-        if (client != null) {
-          clients.add(client);
-        }
-      }
-    }
-    return clients;
-  }
-
-  private static SamlClientIdp parseClient(Element element, Set<String> idsSeen) {
-    String id = element.getAttribute(SAML_ATTR_ENTITY_ID);
-    Preconditions.checkArgument(!idsSeen.contains(id), "Duplicate entity ID in metadata: %s", id);
-    idsSeen.add(id);
-    SamlClientIdp sso = parseSso(id, findChildElement(element, SAML_DESCRIPTOR_IDP_SSO, false));
-    SamlClientIdp pdp = parsePdp(id, findChildElement(element, SAML_DESCRIPTOR_PDP, false));
-    return
-        (sso == null) ? pdp
-        : (pdp == null) ? sso
-        : sso.replacePdp(pdp);
-  }
-
-  private static SamlClientIdp parseSso(String id, Element ssoRole) {
-    if (ssoRole == null) {
-      return null;
-    }
-    Element sso = findChildElement(ssoRole, SAML_SERVICE_SINGLE_SIGN_ON, true);
-    Element ars = findChildElement(ssoRole, SAML_SERVICE_ARTIFACT_RESOLUTION, false);
-    Element kd = findChildElement(ssoRole, SAML_DESCRIPTOR_KEY, false);
-    return SamlClientIdp.makeSso(id,
-        sso.getAttribute(SAML_ATTR_LOCATION),
-        (ars == null) ? null : ars.getAttribute(SAML_ATTR_LOCATION),
-        (kd == null) ? null : keyDescriptorCertificate(kd));
-  }
-
-  private static SamlClientIdp parsePdp(String id, Element pdp) {
-    if (pdp == null) {
-      return null;
-    }
-    Element authz = findChildElement(pdp, SAML_SERVICE_AUTHZ, true);
-    return SamlClientIdp.makePdp(id,
-        (authz == null) ? null : authz.getAttribute(SAML_ATTR_LOCATION));
-  }
-
-  /**
-   * Set the SAML client IdPs in given metadata to the given set.  Removes any
-   * clients already in the metadata, then inserts the given clients.
-   *
-   * @param document The metadata as a {@link Document}.  This document is
-   *     modified to contain the new clients.
-   * @param clients A set of SAML client IdP descriptors; null means delete all.
-   * @throws IOException if metadata can't be parsed or serialized.
-   */
-  public static void setSamlClientsInMetadata(Document document, Collection<SamlClientIdp> clients)
-      throws IOException {
-    if (clients == null) {
-      deleteSamlClients(document);
-      return;
-    }
-    Set<String> idsSeen = Sets.newHashSet();
-    checkSamlClients(idsSeen, clients);
-    deleteSamlClients(document);
-    for (SamlClientIdp client : clients) {
-      addIdpEntity(document, client);
-    }
-  }
-
-  /**
-   * Add the given SAML client IdPs to the given metadata.
-   *
-   * @param document The metadata as a {@link Document}.  This document is
-   *     modified to contain the new clients.
-   * @param clients A set of SAML client IdP descriptors; never null.
-   * @throws IOException if metadata can't be parsed or serialized.
-   */
-  public static void addSamlClientsToMetadata(Document document, Collection<SamlClientIdp> clients)
-      throws IOException {
-    Set<String> idsSeen = Sets.newHashSet();
-    for (SamlClientIdp client : getSamlClientsInMetadata(document)) {
-      idsSeen.add(client.getId());
-    }
-    checkSamlClients(idsSeen, clients);
-    for (SamlClientIdp client : clients) {
-      addIdpEntity(document, client);
-    }
-  }
-
-  private static void checkSamlClients(Set<String> idsSeen, Collection<SamlClientIdp> clients) {
-    for (SamlClientIdp client : clients) {
-      Preconditions.checkArgument(!idsSeen.contains(client.getId()),
-          "Duplicate entity ID in clients: %s", client.getId());
-      idsSeen.add(client.getId());
-    }
-  }
-
-  /**
-   * Find a SAML client with a given entity ID.
-   *
-   * @param entityId The entity ID to look for.
-   * @param clients The clients to look through.
-   * @return The client with that ID, or null if none.
-   */
-  public static SamlClientIdp findSamlClient(String entityId, Iterable<SamlClientIdp> clients) {
-    for (SamlClientIdp client : clients) {
-      if (entityId.equals(client.getId())) {
-        return client;
-      }
-    }
-    return null;
-  }
-
-  // **************** Versions of the above using XML strings ****************
-
-  /**
-   * Get the SAML client IdPs from metadata.
-   *
-   * @param metadata The metadata as XML String.
-   * @return A list of SAML client IdP descriptors.
-   * @throws IOException if metadata can't be parsed.
-   */
-  public static List<SamlClientIdp> getSamlClientsInMetadata(String metadata)
-      throws IOException {
-    return getSamlClientsInMetadata(stringToMetadataDocument(metadata));
-  }
-
-  /**
-   * Set the SAML client IdPs in given metadata to the given set.  Removes any
-   * clients already in the metadata, then inserts the given clients.
-   *
-   * @param origMetadata The original metadata as an XML String.
-   * @param clients The SAML client IdP descriptors; null means delete all.
-   * @return The new metadata as XML String.
-   * @throws IOException if metadata can't be parsed or serialized.
-   */
-  public static String setSamlClientsInMetadata(String origMetadata,
-      Collection<SamlClientIdp> clients)
-      throws IOException {
-    Document document = stringToMetadataDocument(origMetadata);
-    setSamlClientsInMetadata(document, clients);
-    return metadataDocumentToString(document);
-  }
-
-  /**
-   * Add the given SAML client IdPs to the given metadata.
-   *
-   * @param origMetadata The original metadata as an XML String.
-   * @param clients The SAML client IdP descriptors; never null.
-   * @return The new metadata as an XML String.
-   * @throws IOException if metadata can't be parsed or serialized.
-   */
-  public static String addSamlClientsToMetadata(String origMetadata,
-      Collection<SamlClientIdp> clients)
-      throws IOException {
-    Document document = stringToMetadataDocument(origMetadata);
-    addSamlClientsToMetadata(document, clients);
-    return metadataDocumentToString(document);
-  }
-
-  /**
-   * Parse a metadata string into an XML document.
-   *
-   * @param metadata The metadata as an XML string.
-   * @return The SAML metadata document.
-   * @throws IOException if the metadata can't be parsed.
-   */
-  public static Document stringToMetadataDocument(String metadata)
-      throws IOException {
-    return readMetadataDocument(new StringReader(metadata));
-  }
-
-  /**
-   * Convert a metadata XML document into a string.
-   *
-   * @param metadata The SAML metadata document.
-   * @return The metadata as an XML string.
-   * @throws IOException if the metadata can't be converted.
-   */
-  public static String metadataDocumentToString(Document metadata)
-      throws IOException {
-    return XmlUtil.getInstance().buildXmlString(metadata);
-  }
-
-  /**
-   * Read SAML metadata and return it as a DOM document.
-   *
-   * @param input The Reader to read from.
-   * @return The SAML metadata document.
-   * @throws IOException if the document can't be parsed.
-   */
-  public static Document readMetadataDocument(Reader input)
-      throws IOException {
-    Document document = XmlUtil.getInstance().readXmlDocument(input);
-    setConfigParams(document);
-    return document;
-  }
-
-  /**
-   * Write a SAML metadata document as XML.
-   *
-   * @param document The SAML metadata document to write.
-   * @param writer The writer to write it to.
-   * @throws IOException if the document can't be serialized.
-   */
-  public static void writeMetadataDocument(Document document, Writer writer)
-      throws IOException {
-    XmlUtil.getInstance().writeXmlDocument(document, writer);
-  }
-
-  /**
-   * Read SAML metadata and return it as a DOM document.
-   *
-   * @param file The file to read from.
-   * @return The SAML metadata document.
-   * @throws IOException if the document can't be parsed.
-   */
-  public static Document readMetadataDocument(File file)
-      throws IOException {
-    Reader reader = new FileReader(file);
-    try {
-      return readMetadataDocument(reader);
-    } finally {
-      reader.close();
-    }
-  }
-
-  /**
-   * Write a SAML metadata document as XML.
-   *
-   * @param document The SAML metadata document to write.
-   * @param file The file to write it to.
-   * @throws IOException if the document can't be serialized.
-   */
-  public static void writeMetadataDocument(Document document, File file)
-      throws IOException {
-    Writer writer = new FileWriter(file);
-    try {
-      writeMetadataDocument(document, writer);
-    } finally {
-      writer.close();
-    }
-  }
-
-  /**
-   * Make a default metadata document for the security manager, when it is installed
-   * onboard the GSA.  This metadata uses the token "$$GSA$$" to represent the hostname of
-   * the GSA; this token will be dynamically replaced with the real hostname on each
-   * request.  URLs that identify endpoints for connections between the GSA and the
-   * security manager use "localhost".
-   *
-   * @return An XML document representing the metadata.
-   */
-  public static Document makeOnboardSecurityManagerMetadata() {
-    Document document = XmlUtil.getInstance()
-        .makeDocument(SAML_DESCRIPTOR_ENTITIES.getNamespaceURI(),
-            SAML_DESCRIPTOR_ENTITIES.getLocalPart(),
-            null);
-    setConfigParams(document);
-    Element entities = document.getDocumentElement();
-    entities.setAttribute(SAML_ATTR_CACHE_DURATION, SAML_CACHE_DURATION);
-    String gsaEntityId = GSA_ENTITY_ID_ROOT + GSA_ENT_CONFIG_NAME_MARKER;
-    makeGsaEntity(entities, gsaEntityId);
-    makeSmEntity(entities, gsaEntityId + SECMGR_ENTITY_ID_SUFFIX);
-    return document;
-  }
-
-  /**
-   * Make a SAML EntityDescriptor element for the GSA.
-   *
-   * @param entities The SAML EntitiesDescriptor element to put the element in.
-   * @param id The SAML entity ID for the new element.
-   * @return The EntityDescriptor as a DOM element.
-   */
-  private static Element makeGsaEntity(Element entities, String id) {
-    Element entity = makeTopLevelEntity(entities, id, GSA_ENTITY_COMMENT);
-
-    makeRole(entity, SAML_DESCRIPTOR_SP_SSO);
-    makeAssertionConsumer(entity,
-                          SAML_BINDING_HTTP_ARTIFACT,
-                          makeGsaUrl(GSA_HOST_MARKER, GSA_ASSERTION_CONSUMER_PATH));
-
-    makeGoogleOrganization(entity);
-
-    return entity;
-  }
-
-  /**
-   * Make a URL for the GSA.
-   *
-   * @param host The hostname to use.
-   * @param path The URL path.
-   * @return The URL as a string.
-   */
-  private static String makeGsaUrl(String host, String path) {
-    URL url;
-    try {
-      url = new URL(HTTPS_PROTOCOL, host, -1, path);
-    } catch (MalformedURLException e) {
-      throw new IllegalStateException(e);
-    }
-    return url.toString();
-  }
-
-  /**
-   * Make a SAML EntityDescriptor element for the security manager.
-   *
-   * @param entities The SAML EntitiesDescriptor element to put the new element in.
-   * @param id The SAML entity ID for the new element.
-   * @return The EntityDescriptor as a DOM element.
-   */
-  private static Element makeSmEntity(Element entities, String id) {
-    Element entity = makeTopLevelEntity(entities, id, SECMGR_ENTITY_COMMENT);
-    entity.setAttribute(XML_ATTR_ID, SECMGR_ID_FOR_ENTITY);
-
-    makeRole(entity, SAML_DESCRIPTOR_IDP_SSO);
-    makeSingleSignOn(entity, makeSecurityManagerUrl(GSA_HOST_MARKER, SECMGR_SSO_PATH));
-    makeArtifactResolver(entity, makeSecurityManagerUrl(LOCALHOST, SECMGR_ARTIFACT_RESOLVER_PATH));
-
-    makeRole(entity, SAML_DESCRIPTOR_SP_SSO);
-    makeAssertionConsumer(entity,
-                          SAML_BINDING_HTTP_POST,
-                          makeSecurityManagerUrl(GSA_HOST_MARKER, SECMGR_ASSERTION_CONSUMER_PATH));
-    makeAssertionConsumer(entity,
-                          SAML_BINDING_HTTP_ARTIFACT,
-                          makeSecurityManagerUrl(GSA_HOST_MARKER, SECMGR_ASSERTION_CONSUMER_PATH));
-
-    makePdp(entity, makeSecurityManagerUrl(LOCALHOST, SECMGR_AUTHZ_PATH));
-
-    makeGoogleOrganization(entity);
-    return entity;
-  }
-
-  /**
-   * Make a URL for a security manager servlet.
-   *
-   * @param host The hostname to use.
-   * @param servletPath The part of the path that's specific to the servlet.
-   * @return The URL as a string.
-   */
-  private static String makeSecurityManagerUrl(String host, String servletPath) {
-    String path = SECMGR_WEBAPP_PATH + "/" + servletPath;
-    URL url;
-    try {
-      if (LOCALHOST.equals(host)) {
-        url = new URL(HTTP_PROTOCOL, host, path);
-      } else {
-        url = new URL(HTTPS_PROTOCOL, host, path);
-      }
-    } catch (MalformedURLException e) {
-      throw new IllegalStateException(e);
-    }
-    return url.toString();
-  }
-
-  /**
-   * Make a SAML Organization element for Google.
-   *
-   * @param entity The SAML Entity element to put the new element in.
-   * @return The Organization as a DOM element.
-   */
-  private static Element makeGoogleOrganization(Element entity) {
-    Element organization = makeElement(entity, SAML_ORGANIZATION);
-    makeTextElementChild(organization, SAML_ORGANIZATION_NAME, GOOGLE_ORGANIZATION_NAME);
-    makeTextElementChild(organization, SAML_ORGANIZATION_DISPLAY_NAME,
-        GOOGLE_ORGANIZATION_DISPLAY_NAME);
-    makeTextElementChild(organization, SAML_ORGANIZATION_URL, GOOGLE_ORGANIZATION_URL);
-    return organization;
-  }
-
-  /**
-   * Add an external SAML client IdP to a security manager metadata document.  If there is
-   * already an entity with the same ID, it is replaced.
-   *
-   * @param document A security manager metadata document.
-   * @param client A SAML client IdP descriptor.
-   */
-  public static void addIdpEntity(Document document, SamlClientIdp client) {
-    Element clients = getSamlClients(document);
-    if (clients == null) {
-      clients = makeSamlClients(document);
-    }
-    Element entity = makeEntity(clients, client.getId());
-    if (client.hasSso()) {
-      Element role = makeRole(entity, SAML_DESCRIPTOR_IDP_SSO);
-      makeSingleSignOn(entity, client.getUrl());
-      String artifactUrl = normalizeString(client.getArtifactUrl());
-      if (artifactUrl != null) {
-        makeArtifactResolver(entity, artifactUrl);
-      }
-      if (client.getCertificate() != null) {
-        makeKeyDescriptor(role, client.getCertificate());
-      }
-    }
-    if (client.hasPdp()) {
-      makePdp(entity, client.getAuthzServiceUrl());
-    }
-  }
-
-  private static String normalizeString(String s) {
-    if (s == null) {
-      return s;
-    }
-    s = s.trim();
-    return s.isEmpty() ? null : s;
-  }
-
-  /**
-   * Get the SAML EntitiesDescriptor that holds the client entities.
-   *
-   * @param document The SAML metadata document to look in.
-   * @return The EntitiesDescriptor element, or null if no such.
-   */
-  public static Element getSamlClients(Document document) {
-    NodeList nodes =
-        getElementsByQname(document.getDocumentElement(), SAML_DESCRIPTOR_ENTITIES);
-    for (int index = 0; index < nodes.getLength(); index++) {
-      Element element = Element.class.cast(nodes.item(index));
-      if (SECMGR_CLIENTS_ENTITIES_NAME.equals(element.getAttribute(SAML_ATTR_NAME))) {
-        return element;
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Make an empty SAML EntitiesDescriptor to hold client entities.
-   *
-   * @param document The SAML metadata document to look in.
-   * @return The new EntitiesDescriptor as a DOM element.
-   */
-  private static Element makeSamlClients(Document document) {
-    return makeTopLevelEntities(document.getDocumentElement(),
-        SECMGR_CLIENTS_ENTITIES_NAME, SECMGR_CLIENTS_ENTITIES_COMMENT);
-  }
-
-  /**
-   * Remove the SAML client entities descriptor, if there is one.
-   *
-   * @param document The SAML metadata document to look in.
-   */
-  private static void deleteSamlClients(Document document) {
-    Element oldClients = getSamlClients(document);
-    if (oldClients != null) {
-      oldClients.getParentNode().removeChild(oldClients);
-    }
-    for (Comment comment :
-             findChildComments(
-                 document.getDocumentElement(),
-                 SECMGR_CLIENTS_ENTITIES_COMMENT)) {
-      comment.getParentNode().removeChild(comment);
-    }
-  }
-
-
-  // Endpoint constructors.
-
-  /**
-   * Make a SAML SingleSignOn element.
-   *
-   * @param entity The SAML EntityDescriptor to put the new element in.
-   * @param url The endpoint URL for the new element.
-   * @return The new SingleSignOn as a DOM element.
-   */
-  private static Element makeSingleSignOn(Element entity, String url) {
-    return makeEndpoint(findRole(entity, SAML_DESCRIPTOR_IDP_SSO),
-        SAML_SERVICE_SINGLE_SIGN_ON, SAML_BINDING_HTTP_REDIRECT, url);
-  }
-
-  /**
-   * Make a SAML ArtifactResolver element.
-   *
-   * @param entity The SAML EntityDescriptor to put the new element in.
-   * @param url The endpoint URL for the new element.
-   * @return The new ArtifactResolver as a DOM element.
-   */
-  private static Element makeArtifactResolver(Element entity, String url) {
-    return makeIndexedEndpoint(findRole(entity, SAML_DESCRIPTOR_IDP_SSO),
-        SAML_SERVICE_ARTIFACT_RESOLUTION, SAML_BINDING_SOAP, url);
-  }
-
-  /**
-   * Make a SAML AssertionConsumer element.
-   *
-   * @param entity The SAML EntityDescriptor to put the new element in.
-   * @param url The endpoint URL for the new element.
-   * @return The new AssertionConsumer as a DOM element.
-   */
-  private static Element makeAssertionConsumer(Element entity, String binding, String url) {
-    return makeIndexedEndpoint(findRole(entity, SAML_DESCRIPTOR_SP_SSO),
-        SAML_SERVICE_ASSERTION_CONSUMER, binding, url);
-  }
-
-  /**
-   * Make a SAML PDPDescriptor element.
-   *
-   * @param entity The SAML EntityDescriptor to put the new element in.
-   * @param url The endpoint URL for the new element.
-   * @return The new PDPDescriptor as a DOM element.
-   */
-  private static Element makePdp(Element entity, String url) {
-    Element role = makeRole(entity, SAML_DESCRIPTOR_PDP);
-    makeEndpoint(role, SAML_SERVICE_AUTHZ, SAML_BINDING_SOAP, url);
-    return role;
-  }
-
-  /**
-   * Find a role element with a given name.
-   *
-   * @param entity The SAML EntityDescriptor to look in.
-   * @param qname The qname of the role element to look for.
-   * @return The specified role element.
-   * @throws IllegalArgumentException if there's no such child.
-   */
-  private static Element findRole(Element entity, QName qname) {
-    return findChildElement(entity, qname, true);
-  }
-
-
-  // Element constructors.
-
-  /**
-   * Make a new top-level SAML EntitiesDescriptor element.
-   *
-   * @param entities The SAML EntitiesDescriptor to put the new element in.
-   * @param name The name of the new element -- will be put in the name attribute.
-   * @param comment A descriptive comment that will be added as an XML comment.
-   * @return The new EntitiesDescriptor as a DOM element.
-   */
-  private static Element makeTopLevelEntities(Element entities, String name, String comment) {
-    makeTextChild(entities, "\n");
-    makeCommentChild(entities, " " + comment + " ");
-    makeTextChild(entities, "\n");
-    Element result = makeEntities(entities, name);
-    makeTextChild(entities, "\n");
-    return result;
-  }
-
-  /**
-   * Make a new SAML EntitiesDescriptor element.
-   *
-   * @param entities The SAML EntitiesDescriptor to put the new element in.
-   * @param name The name of the new element -- will be put in the name attribute.
-   * @return The new EntitiesDescriptor as a DOM element.
-   */
-  private static Element makeEntities(Element entities, String name) {
-    Element child = makeElementChild(entities, SAML_DESCRIPTOR_ENTITIES);
-    child.setAttribute(SAML_ATTR_NAME, name);
-    return child;
-  }
-
-  /**
-   * Make a new top-level SAML EntityDescriptor element.
-   *
-   * @param entities The SAML EntitiesDescriptor to put the new element in.
-   * @param id The id of the new element -- will be put in the ID attribute.
-   * @param comment A descriptive comment that will be added as an XML comment.
-   * @return The new EntityDescriptor as a DOM element.
-   */
-  private static Element makeTopLevelEntity(Element entities, String id, String comment) {
-    makeTextChild(entities, "\n");
-    makeCommentChild(entities, " " + comment + " ");
-    makeTextChild(entities, "\n");
-    Element entity = makeEntity(entities, id);
-    makeTextChild(entities, "\n");
-    return entity;
-  }
-
-  /**
-   * Make a new SAML EntityDescriptor element.
-   *
-   * @param entities The SAML EntitiesDescriptor to put the new element in.
-   * @param id The id of the new element -- will be put in the ID attribute.
-   * @return The new EntityDescriptor as a DOM element.
-   */
-  private static Element makeEntity(Element entities, String id) {
-    Element old = findEntity(entities, id);
-    Element entity = makeElement(entities, SAML_DESCRIPTOR_ENTITY);
-    entity.setAttribute(SAML_ATTR_ENTITY_ID, id);
-    if (old == null) {
-      entities.appendChild(entity);
-    } else {
-      entities.replaceChild(entity, old);
-    }
-    return entity;
-  }
-
-  /**
-   * Find a SAML EntityDescriptor element.
-   *
-   * @param entities The SAML EntitiesDescriptor to look in.
-   * @param id The id of the element to look for.
-   * @return The specified EntityDescriptor, or null if no such.
-   */
-  private static Element findEntity(Element entities, String id) {
-    NodeList nodes = getElementsByQname(entities, SAML_DESCRIPTOR_ENTITY);
-    for (int index = 0; index < nodes.getLength(); index++) {
-      Element element = Element.class.cast(nodes.item(index));
-      if (id.equals(element.getAttribute(SAML_ATTR_ENTITY_ID))) {
-        return element;
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Make a new SAML role.
-   *
-   * @param entity the SAML EntityDescriptor to put the new role in.
-   * @param qname The qname of the new role.
-   * @return The new role as a DOM element.
-   */
-  private static Element makeRole(Element entity, QName qname) {
-    Element role = makeElementChild(entity, qname);
-    role.setAttribute(SAML_ATTR_PROTOCOL_SUPPORT_ENUMERATION, SAML_PROTOCOL);
-    return role;
-  }
-
-  /**
-   * Make a new SAML endpoint.
-   *
-   * @param role the SAML role to put the new endpoint in.
-   * @param qname The qname of the new endpoint.
-   * @param binding The SAML binding specifier.
-   * @param url The endpoing URL.
-   * @return The new endpoint as a DOM element.
-   */
-  private static Element makeEndpoint(Element role, QName qname, String binding, String url) {
-    Element endpoint = makeElementChild(role, qname);
-    endpoint.setAttribute(SAML_ATTR_BINDING, binding);
-    endpoint.setAttribute(SAML_ATTR_LOCATION, url);
-    return endpoint;
-  }
-
-  /**
-   * Make a new SAML indexed endpoint.
-   *
-   * @param role the SAML role to put the new endpoint in.
-   * @param qname The qname of the new endpoint.
-   * @param binding The SAML binding specifier.
-   * @param url The endpoing URL.
-   * @return The new endpoint as a DOM element.
-   */
-  private static Element makeIndexedEndpoint(
-      Element role, QName qname, String binding, String url) {
-    int nChildren = countChildElements(role, qname);
-    Element endpoint = makeEndpoint(role, qname, binding, url);
-    endpoint.setAttribute(SAML_ATTR_INDEX, Integer.toString(nChildren));
-    endpoint.setAttribute(SAML_ATTR_IS_DEFAULT, (nChildren == 0) ? "true" : "false");
-    return endpoint;
-  }
-
-  /**
-   * Make a new SAML key descriptor.
-   *
-   * @param role the SAML role to put the new descriptor in.
-   * @param certificate The X509 certificate that the descriptor will contain.
-   * @return The new key descriptor as a DOM element.
-   */
-  private static Element makeKeyDescriptor(Element role, String certificate) {
-    Element keyDescriptor = makeElementChild(role, SAML_DESCRIPTOR_KEY);
-    keyDescriptor.setAttribute(SAML_ATTR_USE, SAML_USAGE_SIGNING);
-    Element keyInfo = makeElementChild(keyDescriptor, XMLDSIG_KEY_INFO);
-    Element x509Data = makeElementChild(keyInfo, XMLDSIG_X509_DATA);
-    makeTextElementChild(x509Data, XMLDSIG_X509_CERTIFICATE, normalizeCertificate(certificate));
-    return keyDescriptor;
-  }
-
-  /**
-   * Get the certificate out of a SAML key descriptor.  Works only with key descriptors
-   * created by #makeKeyDescriptor().
-   *
-   * @param keyDescriptor The SAML key descriptor to extract from.
-   * @return The extracted certificate, or null if none such.
-   */
-  private static String keyDescriptorCertificate(Element keyDescriptor) {
-    Element keyInfo = findChildElement(keyDescriptor, XMLDSIG_KEY_INFO, false);
-    if (keyInfo == null) { return null; }
-    Element x509Data = findChildElement(keyInfo, XMLDSIG_X509_DATA, false);
-    if (x509Data == null) { return null; }
-    Element x509Certificate = findChildElement(x509Data, XMLDSIG_X509_CERTIFICATE, false);
-    if (x509Certificate == null) { return null; }
-    NodeList nodes = x509Certificate.getChildNodes();
-    if (nodes.getLength() == 1 && nodes.item(0).getNodeType() == Node.TEXT_NODE) {
-      return normalizeCertificate(nodes.item(0).getNodeValue());
-    }
-    return null;
-  }
-
-  /**
-   * Convert a PEM certificate to normalized form.
-   *
-   * @param s The certificate to normalize.
-   * @return The normalized certificate.
-   */
-  public static String normalizeCertificate(String s) {
-    if (s == null) {
-      return s;
-    }
-    List<String> lines = Lists.newArrayList();
-    for (String line : s.trim().split("\n+")) {
-      lines.add(line.trim());
-    }
-    if (lines.size() == 0) {
-      return null;
-    }
-    // Trim off X509 header/footer if present.
-    if (X509_HEADER.equals(lines.get(0))
-        && X509_FOOTER.equals(lines.get(lines.size() - 1))) {
-      lines.remove(lines.size() - 1);
-      lines.remove(0);
-    }
-    StringBuilder builder = new StringBuilder();
-    for (String line : lines) {
-      builder.append(line);
-      builder.append("\n");
-    }
-    return builder.toString();
-  }
-}
diff --git a/src/com/google/enterprise/secmgr/saml/OpenSamlUtil.java b/src/com/google/enterprise/secmgr/saml/OpenSamlUtil.java
index bb65627..6f822f2 100644
--- a/src/com/google/enterprise/secmgr/saml/OpenSamlUtil.java
+++ b/src/com/google/enterprise/secmgr/saml/OpenSamlUtil.java
@@ -16,14 +16,8 @@
 
 import static org.opensaml.common.xml.SAMLConstants.SAML20P_NS;
 
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.Lists;
-//import com.google.enterprise.secmgr.authncontroller.AuthnSession;
-import com.google.enterprise.secmgr.common.FileUtil;
-import com.google.enterprise.secmgr.common.HttpUtil;
-import com.google.enterprise.secmgr.config.ConfigSingleton;
 
-//import org.jdom.Namespace;
 import org.joda.time.DateTime;
 import org.opensaml.Configuration;
 import org.opensaml.DefaultBootstrap;
@@ -37,9 +31,7 @@
 import org.opensaml.common.binding.artifact.BasicSAMLArtifactMap;
 import org.opensaml.common.binding.artifact.SAMLArtifactMap;
 import org.opensaml.common.binding.artifact.SAMLArtifactMap.SAMLArtifactMapEntry;
-import org.opensaml.common.binding.security.SAMLProtocolMessageXMLSignatureSecurityPolicyRule;
 import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
-import org.opensaml.saml2.binding.security.SAML2HTTPRedirectDeflateSignatureRule;
 import org.opensaml.saml2.core.Action;
 import org.opensaml.saml2.core.Artifact;
 import org.opensaml.saml2.core.ArtifactResolve;
@@ -109,10 +101,7 @@
 import org.opensaml.xml.security.keyinfo.provider.InlineX509DataProvider;
 import org.opensaml.xml.security.keyinfo.provider.RSAKeyValueProvider;
 import org.opensaml.xml.security.trust.TrustEngine;
-import org.opensaml.xml.security.x509.X509Credential;
 import org.opensaml.xml.signature.KeyInfo;
-import org.opensaml.xml.signature.SignatureTrustEngine;
-import org.opensaml.xml.signature.impl.ExplicitKeySignatureTrustEngine;
 import org.w3c.dom.Element;
 
 import java.io.File;
@@ -120,15 +109,11 @@
 import java.security.KeyException;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import java.util.List;
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.annotation.concurrent.Immutable;
-import javax.servlet.http.HttpServletRequest;
 import javax.xml.namespace.QName;
 
 /**
@@ -927,31 +912,6 @@
   }
 
   /**
-   * Run a message decoder.
-   *
-   * @param decoder The message decoder to run.
-   * @param context The message context to pass to the decoder.
-   * @param senderDescription A phrase describing the sender of the message.
-   * @return True only if the message was successfully decode.
-   */
-  /*
-  // Commented out to prevent pulling in AuthnSession.
-  public static boolean runDecoder(MessageDecoder decoder, MessageContext context,
-      AuthnSession session, String senderDescription) {
-    try {
-      decoder.decode(context);
-    } catch (MessageDecodingException e) {
-      LOGGER.warning(session.logMessage("Unable to decode SAML message from " + senderDescription));
-      return false;
-    } catch (SecurityException e) {
-      LOGGER.warning(session.logMessage("Unable to verify signature of SAML message from " +
-              senderDescription));
-      return false;
-    }
-    return true;
-  }*/
-
-  /**
    * Get a string for the current date/time, in the correct format for SAML.
    *
    * @return The corresponding string.
@@ -1024,50 +984,6 @@
     return securityPolicy;
   }
 
-  /**
-   * Get a signature policy rule for XML signatures, using metadata credentials.
-   *
-   * @param request An HTTP request to use for specializing the metadata.
-   * @return An appropriate signature policy rule.
-   * @throws IOException
-   */
-  public static synchronized SecurityPolicyRule getMetadataSignaturePolicyRule(
-      HttpServletRequest request)
-      throws IOException {
-    return new SAMLProtocolMessageXMLSignatureSecurityPolicyRule(
-        getMetadataSignatureTrustEngine(request));
-  }
-
-  /**
-   * Get a signature policy rule for the redirect binding, using metadata credentials.
-   *
-   * @param request An HTTP request to use for specializing the metadata.
-   * @return An appropriate signature policy rule.
-   * @throws IOException
-   */
-  public static synchronized SecurityPolicyRule getMetadataSignaturePolicyRuleForRedirect(
-      HttpServletRequest request)
-      throws IOException {
-    return new SAML2HTTPRedirectDeflateSignatureRule(
-        getMetadataSignatureTrustEngine(request));
-  }
-
-  /**
-   * Make a trust engine that checks signatures using credentials in metadata.
-   *
-   * @param request An HTTP request to use for specializing the metadata.
-   * @return An appropriate signature trust engine.
-   * @throws IOException
-   */
-  public static SignatureTrustEngine getMetadataSignatureTrustEngine(HttpServletRequest request)
-      throws IOException {
-    KeyInfoCredentialResolver keyInfoCredentialResolver = getStandardKeyInfoCredentialResolver();
-    MetadataCredentialResolver credentialResolver =
-        new MetadataCredentialResolver(getMetadata(request).getProvider());
-    credentialResolver.setKeyInfoCredentialResolver(keyInfoCredentialResolver);
-    return new ExplicitKeySignatureTrustEngine(credentialResolver, keyInfoCredentialResolver);
-  }
-
   private static KeyInfoCredentialResolver standardKeyInfoCredentialResolver = null;
 
   /**
@@ -1123,40 +1039,6 @@
   }
 
   /**
-   * Read a PEM-encoded X.509 certificate file and its associated private-key file and
-   * return an {@link X509Credential} object.
-   *
-   * @param certFile The certificate file.
-   * @param keyFile The private-key file.
-   * @return The credential object, never null.
-   * @throws IOException if there's some kind of error reading or converting the files.
-   */
-  public static X509Credential readX509Credential(File certFile, File keyFile)
-      throws IOException {
-    return SecurityHelper.getSimpleCredential(
-        readX509CertificateFile(certFile),
-        readPrivateKeyFile(keyFile));
-  }
-
-  /**
-   * Read a PEM-encoded X.509 certificate file and return it as an {@link X509Certificate}
-   * object.
-   *
-   * @param file The file to read.
-   * @return The certificate object, never null.
-   * @throws IOException if there's some kind of error reading or converting the file.
-   */
-  public static X509Certificate readX509CertificateFile(File file)
-      throws IOException {
-    String base64Cert = FileUtil.readPEMCertificateFile(file);
-    try {
-      return SecurityHelper.buildJavaX509Cert(base64Cert);
-    } catch (CertificateException e) {
-      throw new IOException(e);
-    }
-  }
-
-  /**
    * Read a PEM-encoded private-key file and return it as a {@link PrivateKey} object.
    *
    * @param file The file to read.
@@ -1206,87 +1088,4 @@
         new MapBasedStorageService<String, SAMLArtifactMapEntry>(),
         artifactLifetime);
   }
-
-  /**
-   * Gets an entity descriptor with a given ID.
-   *
-   * @param id The ID of the entity to get.
-   * @param request The servlet request to use for getting the metadata.
-   * @return The entity's descriptor, or {@code null} if there's no entity with
-   *     that ID.
-   */
-  public static EntityDescriptor getEntity(String id, HttpServletRequest request)
-      throws IOException {
-    return getMetadata(request).getEntity(id);
-  }
-
-  /**
-   * Gets the entity descriptor for the security manager.
-   *
-   * @param request The servlet request to use for getting the metadata.
-   * @return The security manager's entity descriptor.
-   */
-  public static EntityDescriptor getSmEntity(HttpServletRequest request)
-      throws IOException {
-    return getMetadata(request).getSmEntity();
-  }
-
-  /**
-   * Gets the entity ID for the security manager.
-   *
-   * @param request The servlet request to use for getting the metadata.
-   * @return The security manager's entity ID.
-   */
-  public static String getSmEntityId(HttpServletRequest request)
-      throws IOException {
-    return getMetadata(request).getSmEntityId();
-  }
-
-  /**
-   * Gets the SAML metadata.
-   *
-   * @param request The servlet request to use for customizing the metadata.
-   * @return The metadata.
-   */
-  public static Metadata getMetadata(HttpServletRequest request)
-      throws IOException {
-    return Metadata.getInstance(HttpUtil.getRequestUrl(request, false));
-  }
-
-  @VisibleForTesting
-  public static Metadata getMetadata()
-      throws IOException {
-    return Metadata.getInstance("localhost");
-  }
-
-  /**
-   * Gets the credential to use for signing outgoing messages.
-   *
-   * @return The credential, or null if unable to obtain.
-   */
-  public static Credential getSigningCredential()
-      throws IOException {
-    String certFileName = ConfigSingleton.getSigningCertificateFilename();
-    String keyFileName = ConfigSingleton.getSigningKeyFilename();
-    if (certFileName == null || keyFileName == null) {
-      LOGGER.info("No signing certificate available for outbound requests");
-      return null;
-    }
-    File certFile = FileUtil.getContextFile(certFileName);
-    File keyFile = FileUtil.getContextFile(keyFileName);
-    if (!certFile.canRead()) {
-      LOGGER.warning("Unable to read signing certificate file: " + certFile);
-      return null;
-    }
-    if (!keyFile.canRead()) {
-      LOGGER.warning("Unable to read signing key file: " + keyFile);
-      return null;
-    }
-    try {
-      return OpenSamlUtil.readX509Credential(certFile, keyFile);
-    } catch (IOException e) {
-      LOGGER.log(Level.WARNING, "Error reading certificate file(s): ", e);
-      return null;
-    }
-  }
 }
diff --git a/src/com/google/enterprise/secmgr/servlets/ResponseParser.java b/src/com/google/enterprise/secmgr/servlets/ResponseParser.java
index 3d82d21..93db806 100644
--- a/src/com/google/enterprise/secmgr/servlets/ResponseParser.java
+++ b/src/com/google/enterprise/secmgr/servlets/ResponseParser.java
@@ -21,7 +21,6 @@
 import com.google.common.collect.Iterables;
 import com.google.enterprise.secmgr.authncontroller.ExportedState;
 import com.google.enterprise.secmgr.common.SecurityManagerUtil;
-import com.google.enterprise.secmgr.identity.Verification;
 import com.google.enterprise.secmgr.modules.SamlClient;
 import com.google.enterprise.secmgr.saml.OpenSamlUtil;
 import com.google.enterprise.secmgr.saml.SamlLogUtil;
@@ -209,21 +208,6 @@
   }
 
   /**
-   * Convert an assertion's expiration time to a form suitable for use in a
-   * verification.
-   *
-   * @param time The given expiration time.
-   * @return An expiration time usable by a verification.
-   */
-  public long expirationTimeToVerificationTime(DateTime time) {
-    if (time != null) {
-      return time.getMillis();
-    }
-    warn("SAML IdP failed to return expiration time");
-    return Verification.NEVER_EXPIRES;
-  }
-
-  /**
    * Gets an exported-state object.  This information is a security manager
    * extension.  Must satisfy {@link #areAssertionsValid} prior to calling.
    */
diff --git a/src/com/google/inject/Inject.java b/src/com/google/inject/Inject.java
deleted file mode 100644
index 92da74e..0000000
--- a/src/com/google/inject/Inject.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2011 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.inject;
-
-/**
- * Mock Inject.
- */
-public @interface Inject {}
diff --git a/src/com/google/inject/Injector.java b/src/com/google/inject/Injector.java
deleted file mode 100644
index 9495d19..0000000
--- a/src/com/google/inject/Injector.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2011 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.inject;
-
-/**
- * Mock Injector.
- */
-public class Injector {
-  public <T> T getInstance(Class<T> clazz) {
-    throw new UnsupportedOperationException();
-  }
-
-  public <T> T getInstance(Key<T> key) {
-    throw new UnsupportedOperationException();
-  }
-}
diff --git a/src/com/google/inject/Key.java b/src/com/google/inject/Key.java
deleted file mode 100644
index be051ff..0000000
--- a/src/com/google/inject/Key.java
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2011 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.inject;
-
-/**
- * Mock Key.
- */
-public class Key<T> {
-  public static <T> Key<T> get(TypeLiteral<T> type) {
-    throw new UnsupportedOperationException();
-  }
-}
diff --git a/src/com/google/inject/Singleton.java b/src/com/google/inject/Singleton.java
deleted file mode 100644
index 0a998f5..0000000
--- a/src/com/google/inject/Singleton.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2011 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.inject;
-
-/**
- * Mock Singleton.
- */
-public @interface Singleton {}
diff --git a/src/com/google/inject/TypeLiteral.java b/src/com/google/inject/TypeLiteral.java
deleted file mode 100644
index 326d6d7..0000000
--- a/src/com/google/inject/TypeLiteral.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2011 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.inject;
-
-/**
- * Mock TypeLiteral.
- */
-public class TypeLiteral<T> {}
diff --git a/src/com/google/inject/name/Named.java b/src/com/google/inject/name/Named.java
deleted file mode 100644
index 41ea9b9..0000000
--- a/src/com/google/inject/name/Named.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2011 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.inject.name;
-
-/**
- * Mock Named.
- */
-public @interface Named {
-  String value();
-}
diff --git a/src/org/springframework/mock/web/MockHttpServletRequest.java b/src/org/springframework/mock/web/MockHttpServletRequest.java
deleted file mode 100644
index 1bef3a7..0000000
--- a/src/org/springframework/mock/web/MockHttpServletRequest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2011 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 org.springframework.mock.web;
-
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * Mock of a mock
- */
-public interface MockHttpServletRequest extends HttpServletRequest {}
diff --git a/test/com/google/enterprise/adaptor/CronSchedulerTest.java b/test/com/google/enterprise/adaptor/CronSchedulerTest.java
index e0be115..68414a6 100644
--- a/test/com/google/enterprise/adaptor/CronSchedulerTest.java
+++ b/test/com/google/enterprise/adaptor/CronSchedulerTest.java
@@ -51,8 +51,10 @@
         scheduler.schedule("0 0 1 1 1-7/2", noopRunnable).toString());
     assertEquals("CronFuture([{0}, {0}, {1, 3, 5, 7, 9, 11}, {0}, {0}])",
         scheduler.schedule("0 0 2-13/2 1 0", noopRunnable).toString());
-    assertEquals("CronFuture([{0}, {0}, {0}, {0}, {0, 1, 2, 3, 4, 5, 6}])",
+    assertEquals("CronFuture([{0}, {0}, {0}, {0}, null])",
         scheduler.schedule("0 0 1 1 *", noopRunnable).toString());
+    assertEquals("CronFuture([{0}, {0}, {0}, {0}, {0, 1, 2, 3, 4, 5, 6}])",
+        scheduler.schedule("0 0 1 1 */1", noopRunnable).toString());
   }
 
   @Test
@@ -152,46 +154,61 @@
     // 1970-02-02T10:02:01Z, which is a Monday. That is 02:02:01 in PST.
     timeProvider.time = 2800921L * 1000;
     atomicCommand.get().run();
-    Thread.sleep(10);
     assertEquals(1, counter.get());
 
     // Wrong minute.
     // 1970-02-02T10:01:01Z, which is a Monday. That is 02:01:01 in PST.
     timeProvider.time = 2800861L * 1000;
     atomicCommand.get().run();
-    Thread.sleep(10);
     assertEquals(1, counter.get());
 
     // Wrong hour.
     // 1970-02-02T09:02:01Z, which is a Monday. That is 01:02:01 in PST.
     timeProvider.time = 2797321L * 1000;
     atomicCommand.get().run();
-    Thread.sleep(10);
     assertEquals(1, counter.get());
 
     // Wrong day of month.
     // 1970-02-02T10:02:01Z, which is a Monday. That is 02:02:01 in PST.
     timeProvider.time = 2800921L * 1000;
-    scheduler.reschedule(future, "2 2 1 2 2");
+    scheduler.reschedule(future, "2 2 1 2 *");
     atomicCommand.get().run();
-    Thread.sleep(10);
     assertEquals(1, counter.get());
 
     // Wrong month.
     // 1970-02-02T10:02:01Z, which is a Monday. That is 02:02:01 in PST.
     timeProvider.time = 2800921L * 1000;
-    scheduler.reschedule(future, "2 2 2 1 2");
+    scheduler.reschedule(future, "2 2 2 1 1");
     atomicCommand.get().run();
-    Thread.sleep(10);
     assertEquals(1, counter.get());
 
     // Wrong day of week.
     // 1970-02-02T10:02:01Z, which is a Monday. That is 02:02:01 in PST.
     timeProvider.time = 2800921L * 1000;
+    scheduler.reschedule(future, "2 2 * 2 2");
+    atomicCommand.get().run();
+    assertEquals(1, counter.get());
+
+    // Wrong day of week and day of month.
+    // 1970-02-02T10:02:01Z, which is a Monday. That is 02:02:01 in PST.
+    timeProvider.time = 2800921L * 1000;
+    scheduler.reschedule(future, "2 2 1 2 2");
+    atomicCommand.get().run();
+    assertEquals(1, counter.get());
+
+    // Wrong day of week, but right day of month.
+    // 1970-02-02T10:02:01Z, which is a Monday. That is 02:02:01 in PST.
+    timeProvider.time = 2800921L * 1000;
     scheduler.reschedule(future, "2 2 2 2 2");
     atomicCommand.get().run();
-    Thread.sleep(10);
-    assertEquals(1, counter.get());
+    assertEquals(2, counter.get());
+
+    // Wrong day of month, but right day of week.
+    // 1970-02-02T10:02:01Z, which is a Monday. That is 02:02:01 in PST.
+    timeProvider.time = 2800921L * 1000;
+    scheduler.reschedule(future, "2 2 1 2 1");
+    atomicCommand.get().run();
+    assertEquals(3, counter.get());
   }
 
   @Test
diff --git a/test/com/google/enterprise/adaptor/HttpClientAdapterTest.java b/test/com/google/enterprise/adaptor/HttpClientAdapterTest.java
deleted file mode 100644
index 21db551..0000000
--- a/test/com/google/enterprise/adaptor/HttpClientAdapterTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-// 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;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-import org.junit.rules.ExpectedException;
-
-/**
- * Test cases for {@link HttpClientAdapter}.
- */
-public class HttpClientAdapterTest {
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  private HttpClientAdapter httpClient = new HttpClientAdapter();
-
-  @Test
-  public void testHeadExchange() {
-    thrown.expect(UnsupportedOperationException.class);
-    httpClient.headExchange(null);
-  }
-
-  @Test
-  public void testGetExchange() {
-    thrown.expect(UnsupportedOperationException.class);
-    httpClient.getExchange(null);
-  }
-
-  @Test
-  public void testNewHttpExchange() {
-    thrown.expect(UnsupportedOperationException.class);
-    httpClient.newHttpExchange(null);
-  }
-
-  @Test
-  public void testGetConnection() throws Exception {
-    thrown.expect(UnsupportedOperationException.class);
-    httpClient.getConnection(null);
-  }
-
-  @Test
-  public void testHeadExchange2() {
-    thrown.expect(UnsupportedOperationException.class);
-    httpClient.headExchange(null, null);
-  }
-
-  @Test
-  public void testGetExchange2() {
-    thrown.expect(UnsupportedOperationException.class);
-    httpClient.getExchange(null, null);
-  }
-
-  @Test
-  public void testPostExchange3() {
-    thrown.expect(UnsupportedOperationException.class);
-    httpClient.postExchange(null, null, null);
-  }
-
-  @Test
-  public void testNewHttpExchange2() {
-    thrown.expect(UnsupportedOperationException.class);
-    httpClient.newHttpExchange(null, null);
-  }
-
-  @Test
-  public void testSetRequestTimeoutMillis() {
-    thrown.expect(UnsupportedOperationException.class);
-    httpClient.setRequestTimeoutMillis(-1);
-  }
-}
diff --git a/test/com/google/enterprise/adaptor/MockHttpClient.java b/test/com/google/enterprise/adaptor/MockHttpClient.java
index ab3f35f..734f260 100644
--- a/test/com/google/enterprise/adaptor/MockHttpClient.java
+++ b/test/com/google/enterprise/adaptor/MockHttpClient.java
@@ -15,8 +15,6 @@
 package com.google.enterprise.adaptor;
 
 import com.google.common.collect.ListMultimap;
-import com.google.enterprise.secmgr.common.CookieStore;
-import com.google.enterprise.secmgr.common.GCookie;
 import com.google.enterprise.secmgr.http.HttpClientInterface;
 import com.google.enterprise.secmgr.http.HttpExchange;
 
@@ -36,16 +34,6 @@
   protected abstract void handleExchange(ClientExchange ex);
 
   @Override
-  public HttpExchange headExchange(URL url) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public HttpExchange getExchange(URL url) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
   public HttpExchange postExchange(URL url,
                                    ListMultimap<String, String> parameters) {
     HttpExchange exchange = new ClientExchange(url, "POST");
@@ -61,42 +49,6 @@
     return exchange;
   }
 
-  @Override
-  public HttpExchange newHttpExchange(URL url) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public Connection getConnection(URL url) throws IOException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public HttpExchange headExchange(Connection connection, URL url) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public HttpExchange getExchange(Connection connection, URL url) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public HttpExchange postExchange(Connection connection, URL url,
-                                   ListMultimap<String, String> parameters) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public HttpExchange newHttpExchange(Connection connection, URL url) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void setRequestTimeoutMillis(int millisec) {
-    throw new UnsupportedOperationException();
-  }
-
   /** Mocked exchange that calls {@link #handleExchange}. */
   protected class ClientExchange implements HttpExchange {
     private final URL url;
@@ -173,16 +125,6 @@
       return requestHeaders.getFirst(headerName);
     }
 
-    @Override
-    public void addCookies(Iterable<GCookie> cookies) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public CookieStore getCookies() {
-      throw new UnsupportedOperationException();
-    }
-
     /** Does not copy provided byte array. */
     @Override
     public void setRequestBody(byte[] byteArrayRequestEntity) {
diff --git a/test/com/google/enterprise/adaptor/SamlIdentityProviderTest.java b/test/com/google/enterprise/adaptor/SamlIdentityProviderTest.java
index 8b67eba..56d0bcb 100644
--- a/test/com/google/enterprise/adaptor/SamlIdentityProviderTest.java
+++ b/test/com/google/enterprise/adaptor/SamlIdentityProviderTest.java
@@ -92,8 +92,11 @@
     assertTrue(samlResponse.contains("https://entyo36.hot.corp.google.com/"
         + "security-manager/samlassertionconsumer"));
     assertTrue(samlResponse.contains("user1"));
-    assertTrue(samlResponse.contains("group1"));
-    assertTrue(samlResponse.contains("group2"));
+    assertTrue(samlResponse.contains(
+        "<saml2:AttributeStatement><saml2:Attribute Name=\"member-of\">"
+        + "<saml2:AttributeValue>group1</saml2:AttributeValue>"
+        + "<saml2:AttributeValue>group2</saml2:AttributeValue>"
+        + "</saml2:Attribute></saml2:AttributeStatement>"));
   }
 
   @Test