Fixes per pjo
diff --git a/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/ResponseHandler.java b/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/AuthNResponseHandler.java
similarity index 73%
rename from src/com/google/enterprise/adaptor/examples/HelloWorldConnector/ResponseHandler.java
rename to src/com/google/enterprise/adaptor/examples/HelloWorldConnector/AuthNResponseHandler.java
index 76bbedc..0ff4144 100644
--- a/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/ResponseHandler.java
+++ b/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/AuthNResponseHandler.java
@@ -1,3 +1,5 @@
+package com.google.enterprise.adaptor.examples.HelloWorldConnector;
+
 // Copyright 2014 Google Inc. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,12 +17,12 @@
 import com.google.enterprise.adaptor.AdaptorContext;
 import com.google.enterprise.adaptor.AuthnAuthority.Callback;
 import com.google.enterprise.adaptor.Session;
-import com.google.enterprise.adaptor.UserPrincipal;
 
 import com.sun.net.httpserver.HttpExchange;
 import com.sun.net.httpserver.HttpHandler;
 
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
 import java.util.HashMap;
 import java.util.Map;
@@ -32,42 +34,53 @@
  * <ol>
  * <li>Retrieve the previously stored callback object.
  * <li>Retrieve the userid from the query parameters. 
- * Again, this is just to illustrate the point - it can be a userid from another service. 
- * It also skips the user authentication process and goes directly to step three.
+ * Again, this is just to illustrate the point - it can be a userid from 
+ * another service. 
+ * It also skips the user authentication process and goes directly to step 
+ * three.
  * <li>Constructs a AuthnIdentity object, 
  * and pass on to callback.userAuthenticated(). 
  * You can set both userid and groups on the identity object.
  */
-public class ResponseHandler implements HttpHandler {
-  private static final Logger log = 
-      Logger.getLogger(ResponseHandler.class.getName());
+public class AuthNResponseHandler implements HttpHandler {
+  private static final Logger log =
+      Logger.getLogger(AuthNResponseHandler.class.getName());
   private AdaptorContext context;
-
-  public ResponseHandler(AdaptorContext adaptorContext) {
-    context = adaptorContext;
+  private Callback callback;
+  
+  public AuthNResponseHandler(AdaptorContext adaptorContext) {
+    context = adaptorContext; 
   }
 
-  @SuppressWarnings("rawtypes")
   @Override
   public void handle(HttpExchange ex) throws IOException {
     log.info("handle");
-    Session session = context.getUserSession(ex, false);
-    Callback callback = (Callback) session.getAttribute("callback");
+   
+    callback = getCallback(ex);
     if (callback == null) {
-      log.warning("Something is wrong, callback object is misssing");
       return;
     }
-    Map parameters = extractQueryParams(ex.getRequestURI().toString());
+    
+    Map<String, String> parameters = 
+        extractQueryParams(ex.getRequestURI().toString());
     if (parameters.size() == 0 || null == parameters.get("userid")) {
       log.warning("missing userid");
       callback.userAuthenticated(ex, null);
       return;
     }
-    String userid = (String) parameters.get("userid");
-    MyAuthnIdentity identity = new MyAuthnIdentity();
-    identity.setUser(new UserPrincipal(userid));
+    String userid = parameters.get("userid");
+    MyAuthnIdentity identity = new MyAuthnIdentity(userid);
     callback.userAuthenticated(ex, identity);
   }
+  
+  private Callback getCallback(HttpExchange ex) {
+    Session session = context.getUserSession(ex, false);
+    Callback callback = (Callback)session.getAttribute("callback");
+    if (callback == null) {
+      log.warning("Something is wrong, callback object is misssing");
+    }
+    return callback;
+  }
 
   public Map<String, String> extractQueryParams(String request) {
     String query = request.substring(request.lastIndexOf("?") + 1);
@@ -79,7 +92,7 @@
         paramMap.put(URLDecoder.decode(param[0], "UTF-8"),
             URLDecoder.decode(param[1], "UTF-8"));
       }
-    } catch (Exception e) {
+    } catch (UnsupportedEncodingException e) {
       log.warning(e.getMessage());
     }
     return paramMap;
diff --git a/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/HelloWorldAuthenticator.java b/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/HelloWorldAuthenticator.java
index 86e32f4..cb2c5ae 100644
--- a/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/HelloWorldAuthenticator.java
+++ b/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/HelloWorldAuthenticator.java
@@ -1,3 +1,5 @@
+package com.google.enterprise.adaptor.examples.HelloWorldConnector;
+
 // Copyright 2014 Google Inc. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -36,23 +38,27 @@
  */
 public class HelloWorldAuthenticator implements AuthnAuthority, AuthzAuthority {
 
-  private static final Logger log = 
-      Logger.getLogger(HelloWorldConnector.class.getName());
+  private static final Logger log =
+      Logger.getLogger(HelloWorldAuthenticator.class.getName());
 
   AdaptorContext context;
 
   public HelloWorldAuthenticator(AdaptorContext adaptorContext) {
-    context = adaptorContext;
+    if (adaptorContext == null) {
+      throw new NullPointerException();
+    } else {
+      context = adaptorContext;
+    }
   }
 
   @Override
   public void authenticateUser(HttpExchange exchange, Callback callback)
       throws IOException {
-    
+
     log.info("redirect");
     context.getUserSession(exchange, true).setAttribute("callback",
         callback);
-    
+
     Headers responseHeaders = exchange.getResponseHeaders();
     responseHeaders.set("Content-Type", "text/html");
     exchange.sendResponseHeaders(200, 0);
@@ -66,14 +72,14 @@
     os.close();
     exchange.close();
   }
-  
+
   @Override
   public Map<DocId, AuthzStatus> isUserAuthorized(AuthnIdentity userIdentity,
       Collection<DocId> ids) throws IOException {
 
-    HashMap<DocId, AuthzStatus> authorizedDocs = 
+    HashMap<DocId, AuthzStatus> authorizedDocs =
         new HashMap<DocId, AuthzStatus>();
-    
+
     for (Iterator<DocId> iterator = ids.iterator(); iterator.hasNext();) {
       DocId docId = iterator.next();
       // if authorized
diff --git a/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/HelloWorldConnector.java b/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/HelloWorldConnector.java
index 72c18cb..186d804 100644
--- a/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/HelloWorldConnector.java
+++ b/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/HelloWorldConnector.java
@@ -1,3 +1,5 @@
+package com.google.enterprise.adaptor.examples.HelloWorldConnector;
+
 // Copyright 2014 Google Inc. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,6 +30,7 @@
 import java.io.OutputStreamWriter;
 import java.io.Writer;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
@@ -38,240 +41,226 @@
  * Demonstrates what code is necessary for putting public content onto a GSA.
  * The key operations are:
  * <ol>
- * <li>providing document ids
- * <li>providing document bytes given a document id
+ * <li>providing document ids either by Lister or Graph Traversal
+ * <li>providing document bytes and metadata given a document id
  * </ol>
  */
 public class HelloWorldConnector extends AbstractAdaptor implements
     PollingIncrementalLister {
 
-    private static final Logger log = 
-        Logger.getLogger(HelloWorldConnector.class.getName());
-    int requestCount = 1, requestCount2 = 1;
+  private static final Logger log =
+      Logger.getLogger(HelloWorldConnector.class.getName());
+  private boolean provideBodyOfDoc1003 = true;
 
-    @Override
-    public void init(AdaptorContext context) throws Exception {
-      context.setPollingIncrementalLister(this);
-      HelloWorldAuthenticator authenticator = 
-          new HelloWorldAuthenticator(context);
-      context.setAuthnAuthority(authenticator);
-      context.setAuthzAuthority(authenticator);
-      context.createHttpContext("/google-response", 
-          new ResponseHandler(context));
-    }
+  @Override
+  public void init(AdaptorContext context) throws Exception {
+    context.setPollingIncrementalLister(this);
+    HelloWorldAuthenticator authenticator =
+        new HelloWorldAuthenticator(context);
+    context.setAuthnAuthority(authenticator);
+    context.setAuthzAuthority(authenticator);
+    context.createHttpContext("/google-response",
+        new AuthNResponseHandler(context));
+  }
 
-    /** Full crawl **/
-    @Override
-    public void getDocIds(DocIdPusher pusher) throws InterruptedException {
-      ArrayList<DocId> mockDocIds = new ArrayList<DocId>();
-      // push docids
-      mockDocIds.add(new DocId(""));
-      pusher.pushDocIds(mockDocIds);
-      // push records
-      DocIdPusher.Record record = new DocIdPusher.Record.Builder(new DocId(
-          "1009")).setCrawlImmediately(true).setLastModified(new Date())
-          .build();
-      pusher.pushRecords(Collections.singleton(record));
-      // push named resources
-      HashMap<DocId, Acl> aclParent = new HashMap<DocId, Acl>();
-      ArrayList<Principal> permits = new ArrayList<Principal>();
-      permits.add(new UserPrincipal("user1", "Default"));
-      aclParent.put(new DocId("fakeID"), new Acl.Builder()
+  /**
+   * This example shows how to use both the Lister & Graph Traversal.
+   * The root document ("") is a virtual doc which will contain a list of
+   * links to other docs when returned by the Retriever.
+   * If you aren't using Graph Traversal, all docid's would be pushed in
+   * like 1001 and 1002
+   */
+  @Override
+  public void getDocIds(DocIdPusher pusher) throws InterruptedException {
+    ArrayList<DocId> mockDocIds = new ArrayList<DocId>();
+    // push docids
+    mockDocIds.add(new DocId(""));
+    mockDocIds.add(new DocId("1001"));
+    mockDocIds.add(new DocId("1002"));
+    pusher.pushDocIds(mockDocIds);
+    // push records
+    DocIdPusher.Record record = new DocIdPusher.Record.Builder(new DocId(
+        "1009")).setCrawlImmediately(true).setLastModified(new Date())
+        .build();
+    pusher.pushRecords(Collections.singleton(record));
+    // push named resources
+    HashMap<DocId, Acl> aclParent = new HashMap<DocId, Acl>();
+    ArrayList<Principal> permits = new ArrayList<Principal>();
+    permits.add(new UserPrincipal("user1", "Default"));
+    aclParent.put(new DocId("fakeID"), new Acl.Builder()
         .setEverythingCaseInsensitive().setPermits(permits)
         .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
         .build());
-      pusher.pushNamedResources(aclParent);
-      //push groups
-      // pusher.pushGroupDefinitions(defs, caseSensitive, handler)
-    }
+    pusher.pushNamedResources(aclParent);
+  }
 
-    /** Gives the bytes of a document referenced with id. */
-    @Override
-    public void getDocContent(Request req, Response resp) throws IOException {  
-      DocId id = req.getDocId();
-      log.info("DocId '" + id.getUniqueId() + "'");
+  /** Gives the bytes of a document referenced with id. */
+  @Override
+  public void getDocContent(Request req, Response resp) throws IOException {
+    DocId id = req.getDocId();
+    log.info("DocId '" + id.getUniqueId() + "'");
 
-      // Hard-coded list of our doc id's
-      if ("".equals(id.getUniqueId())) {
-        // this is a the root folder, write some URLs
+    // Hard-coded list of our doc id's
+    if ("".equals(id.getUniqueId())) {
+      // this is a the root folder, write some URLs
+      Writer writer = new OutputStreamWriter(resp.getOutputStream());
+      writer.write("<!DOCTYPE html>\n<html><body>");
+      writer.write("<br></br>");
+      writer.write("<a href=\"1001\">doc_not_changed</a>");
+      writer.write("<br></b r>");
+      writer.write("<a href=\"1002\">doc_changed</a>");
+      writer.write("<br></br>");
+      writer.write("<a href=\"1003\">doc_deleted</a>");
+      writer.write("<br></br>");
+      writer.write("<a href=\"1004\">doc_with_meta</a>");
+      writer.write("<br></br>");
+      writer.write("<a href=\"1005\">doc_with_ACL</a>");
+      writer.write("<br></br>");
+      writer.write("<a href=\"1006\">doc_with_ACL_Inheritance</a>");
+      writer.write("<br></br>");
+      writer.write("<a href=\"1007\">doc_with_Fragment</a>");
+      writer.write("<br></br>");
+      writer.write("<a href=\"1008\">doc_with_Fragment</a>");
+      writer.write("<br></br>");
+      writer.write("</body></html>");
+      writer.close();
+    } else if ("1001".equals(id.getUniqueId())) {
+      // Example with If-Modified-Since
+      Date lastModifiedDate = req.getLastAccessTime();
+      if (req.hasChangedSinceLastAccess(lastModifiedDate) ||
+          lastModifiedDate == null) {
+        log.info("First Access or no LastModified");
+        resp.setLastModified(new Date());
         Writer writer = new OutputStreamWriter(resp.getOutputStream());
-        writer.write("<!DOCTYPE html>\n<html><body>");
-        writer.write("<br></br>");
-        writer.write("<a href=\"1001\">doc_not_changed</a>");
-        writer.write("<br></b r>");
-        writer.write("<a href=\"1002\">doc_changed</a>");
-        writer.write("<br></br>");
-        writer.write("<a href=\"1003\">doc_deleted</a>");
-        writer.write("<br></br>");
-        writer.write("<a href=\"1004\">doc_with_meta</a>");
-        writer.write("<br></br>");
-        writer.write("<a href=\"1005\">doc_with_ACL</a>");
-        writer.write("<br></br>");
-        writer.write("<a href=\"1006\">doc_with_ACL_Inheritance</a>");
-        writer.write("<br></br>");
-        writer.write("<a href=\"1007\">doc_with_Fragment</a>");
-        writer.write("<br></br>");
-        writer.write("<a href=\"1008\">doc_with_Fragment</a>");
-        writer.write("<br></br>");
-        writer.write("</body></html>");
+        writer.write("Menu 1001 says latte");
         writer.close();
-      } else if ("1001".equals(id.getUniqueId())) {
-        // Example with If-Modified-Since
-        req.hasChangedSinceLastAccess(new Date());
-        if (req.getLastAccessTime() != null) { 
-          // GSA is asking whether anything changed
-          log.info("asked for last access");
-          resp.respondNotModified();
-        } else {
-          log.info("No asked for last access");
-          resp.setLastModified(new Date());
-          Writer writer = new OutputStreamWriter(resp.getOutputStream());
-          writer.write("Menu 1001 says latte");
-          writer.close();
-        }
-      } else if ("1002".equals(id.getUniqueId())) {
-        // Very basic doc
-        Writer writer = new OutputStreamWriter(resp.getOutputStream());
-        writer.write("Menu 1002 says cappuccino");
-        writer.close();
-      } else if ("1003".equals(id.getUniqueId())) {
-        // Alternate between doc and a 404 response
-        if (requestCount2 == 1) {
-          Writer writer = new OutputStreamWriter(resp.getOutputStream());
-          writer.write("Menu 1003 says machiato");
-          writer.close();
-          requestCount2 = 0;
-        } else {
-          resp.respondNotFound();
-          requestCount2 = 1;
-        }
-      } else if ("1004".equals(id.getUniqueId())) {
-        // doc with metdata & different display URL
-        try {
-          resp.addMetadata("flavor", "vanilla");
-          resp.addMetadata("flavor", "hazel nuts");
-          resp.addMetadata("taste", "strawberry");
-          resp.setDisplayUrl(new URI("http://fake.com/a"));
-          Writer writer = new OutputStreamWriter(resp.getOutputStream());
-          writer.write("Menu 1004 says espresso");
-          writer.close();
-        } catch (Exception e) {
-          log.info(e.getMessage());
-        }
-      } else if ("1005".equals(id.getUniqueId())) {
-        // doc with ACLs
-        try {
-          ArrayList<Principal> permits = new ArrayList<Principal>();
-          permits.add(new UserPrincipal("user1", "Default"));
-          permits.add(new UserPrincipal("eric", "Default"));
-          permits.add(new GroupPrincipal("group1", "Default"));
-          ArrayList<Principal> denies = new ArrayList<Principal>();
-          denies.add(new UserPrincipal("user2", "Default"));
-          denies.add(new GroupPrincipal("group2", "Default"));
-          
-          resp.setAcl(new Acl.Builder()
-              .setEverythingCaseInsensitive()
-              .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
-              .setPermits(permits).setDenies(denies).build());
-          
-          Writer writer = new OutputStreamWriter(resp.getOutputStream());
-          writer.write("Menu 1005 says americano");
-          writer.close();
-        } catch (Exception e) {
-          log.info(e.getMessage());
-        }
-      } else if ("1006".equals(id.getUniqueId())) {
-        // Inherit ACLs from 1005
-        try {
-          ArrayList<Principal> permits = new ArrayList<Principal>();
-          permits.add(new GroupPrincipal("group3", "Default"));
-          ArrayList<Principal> denies = new ArrayList<Principal>();
-          denies.add(new GroupPrincipal("group3", "Default"));
-          
-          resp.setAcl(new Acl.Builder()
-              .setEverythingCaseInsensitive()
-              .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
-              .setInheritFrom(new DocId("1005")).setPermits(permits)
-              .setDenies(denies).build());
-          
-          Writer writer = new OutputStreamWriter(resp.getOutputStream());
-          writer.write("Menu 1006 says misto");
-          writer.close();
-        } catch (Exception e) {
-          log.info(e.getMessage());
-        }
-      } else if ("1007".equals(id.getUniqueId())) {
-        // Inherit ACLs from 1005 & 1006
-        try {
-          ArrayList<Principal> permits = new ArrayList<Principal>();
-          permits.add(new GroupPrincipal("group5", "Default"));
-          
-          resp.putNamedResource("Whatever", new Acl.Builder()
-              .setEverythingCaseInsensitive()
-              .setInheritFrom(new DocId("1006"))
-              .setPermits(permits)
-              .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
-              .build());
-          
-          ArrayList<Principal> permits2 = new ArrayList<Principal>();
-          permits2.add(new GroupPrincipal("group4", "Default"));
-          ArrayList<Principal> denies = new ArrayList<Principal>();
-          denies.add(new GroupPrincipal("group4", "Default"));
-          
-          resp.setAcl(new Acl.Builder()
-              .setEverythingCaseInsensitive()
-              .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
-              .setInheritFrom(new DocId("1005")).setPermits(permits2)
-              .setDenies(denies).build());
-          
-          Writer writer = new OutputStreamWriter(resp.getOutputStream());
-          writer.write("Menu 1006 says frappuccino");
-          writer.close();
-        } catch (Exception e) {
-          log.info(e.getMessage());
-        }
-      } else if ("1008".equals(id.getUniqueId())) {
-        // Inherit ACLs from 1007
-        try {
-          ArrayList<Principal> denies = new ArrayList<Principal>();
-          denies.add(new GroupPrincipal("group5", "Default"));
-          
-          resp.setAcl(new Acl.Builder()
-              .setEverythingCaseInsensitive()
-              .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
-              .setInheritFrom(new DocId("1007"), "Whatever")
-              .setDenies(denies).build());
-          Writer writer = new OutputStreamWriter(resp.getOutputStream());
-          writer.write("Menu 1008 says coffee");
-          writer.close();
-        } catch (Exception e) {
-          log.info(e.getMessage());
-        }
-      } else if ("1009".equals(id.getUniqueId())) {
-        // Late Binding (security handled by connector)
-        try {
-          resp.setSecure(true);
-          Writer writer = new OutputStreamWriter(resp.getOutputStream());
-          writer.write("Menu 1009 says espresso");
-          writer.close();
-        } catch (Exception e) {
-          log.info(e.getMessage());
-        }
       } else {
-        resp.respondNotFound();        
+        log.info("Not Modified");
+        resp.respondNotModified();
       }
+    } else if ("1002".equals(id.getUniqueId())) {
+      // Very basic doc
+      Writer writer = new OutputStreamWriter(resp.getOutputStream());
+      writer.write("Menu 1002 says cappuccino");
+      writer.close();
+    } else if ("1003".equals(id.getUniqueId())) {
+      // Alternate between doc and a 404 response
+      if (provideBodyOfDoc1003) {
+        Writer writer = new OutputStreamWriter(resp.getOutputStream());
+        writer.write("Menu 1003 says machiato");
+        writer.close();
+        provideBodyOfDoc1003 = !provideBodyOfDoc1003;
+      } else {
+        resp.respondNotFound();
+        provideBodyOfDoc1003 = !provideBodyOfDoc1003;
+      }
+    } else if ("1004".equals(id.getUniqueId())) {
+      // doc with metdata & different display URL
+        resp.addMetadata("flavor", "vanilla");
+        resp.addMetadata("flavor", "hazel nuts");
+        resp.addMetadata("taste", "strawberry");
+        try {
+          resp.setDisplayUrl(new URI("http://fake.com/a"));
+        } catch (URISyntaxException e) {
+          log.info(e.getMessage());
+        }
+        Writer writer = new OutputStreamWriter(resp.getOutputStream());
+        writer.write("Menu 1004 says espresso");
+        writer.close();
+    } else if ("1005".equals(id.getUniqueId())) {
+      // doc with ACLs
+      ArrayList<Principal> permits = new ArrayList<Principal>();
+      permits.add(new UserPrincipal("user1", "Default"));
+      permits.add(new UserPrincipal("eric", "Default"));
+      permits.add(new GroupPrincipal("group1", "Default"));
+      ArrayList<Principal> denies = new ArrayList<Principal>();
+      denies.add(new UserPrincipal("user2", "Default"));
+      denies.add(new GroupPrincipal("group2", "Default"));
+
+      resp.setAcl(new Acl.Builder()
+          .setEverythingCaseInsensitive()
+          .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
+          .setPermits(permits).setDenies(denies).build());
+
+      Writer writer = new OutputStreamWriter(resp.getOutputStream());
+      writer.write("Menu 1005 says americano");
+      writer.close();
+    } else if ("1006".equals(id.getUniqueId())) {
+      // Inherit ACLs from 1005
+      ArrayList<Principal> permits = new ArrayList<Principal>();
+      permits.add(new GroupPrincipal("group3", "Default"));
+      ArrayList<Principal> denies = new ArrayList<Principal>();
+      denies.add(new GroupPrincipal("group3", "Default"));
+
+      resp.setAcl(new Acl.Builder()
+          .setEverythingCaseInsensitive()
+          .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
+          .setInheritFrom(new DocId("1005")).setPermits(permits)
+          .setDenies(denies).build());
+
+      Writer writer = new OutputStreamWriter(resp.getOutputStream());
+      writer.write("Menu 1006 says misto");
+      writer.close();
+    } else if ("1007".equals(id.getUniqueId())) {
+      // Inherit ACLs from 1005 & 1006
+      ArrayList<Principal> permits = new ArrayList<Principal>();
+      permits.add(new GroupPrincipal("group5", "Default"));
+
+      resp.putNamedResource("Whatever", new Acl.Builder()
+          .setEverythingCaseInsensitive()
+          .setInheritFrom(new DocId("1006"))
+          .setPermits(permits)
+          .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
+          .build());
+
+      ArrayList<Principal> permits2 = new ArrayList<Principal>();
+      permits2.add(new GroupPrincipal("group4", "Default"));
+      ArrayList<Principal> denies = new ArrayList<Principal>();
+      denies.add(new GroupPrincipal("group4", "Default"));
+
+      resp.setAcl(new Acl.Builder()
+          .setEverythingCaseInsensitive()
+          .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
+          .setInheritFrom(new DocId("1005")).setPermits(permits2)
+          .setDenies(denies).build());
+
+      Writer writer = new OutputStreamWriter(resp.getOutputStream());
+      writer.write("Menu 1006 says frappuccino");
+      writer.close();
+    } else if ("1008".equals(id.getUniqueId())) {
+      // Inherit ACLs from 1007
+      ArrayList<Principal> denies = new ArrayList<Principal>();
+      denies.add(new GroupPrincipal("group5", "Default"));
+
+      resp.setAcl(new Acl.Builder()
+      .setEverythingCaseInsensitive()
+      .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
+      .setInheritFrom(new DocId("1007"), "Whatever")
+      .setDenies(denies).build());
+      Writer writer = new OutputStreamWriter(resp.getOutputStream());
+      writer.write("Menu 1008 says coffee");
+      writer.close();
+    } else if ("1009".equals(id.getUniqueId())) {
+      // Late Binding (security handled by connector)
+      resp.setSecure(true);
+      Writer writer = new OutputStreamWriter(resp.getOutputStream());
+      writer.write("Menu 1009 says espresso");
+      writer.close();
+    } else {
+      resp.respondNotFound();
     }
-    
-    @Override
-    public void getModifiedDocIds(DocIdPusher pusher) throws IOException, 
-        InterruptedException {
-      ArrayList<DocId> mockDocIds = new ArrayList<DocId>();
-      mockDocIds.add(new DocId("1002"));
-      pusher.pushDocIds(mockDocIds);    
-    }  
-    
-    /** Call default main for adaptors. */
-    public static void main(String[] args) {
-      AbstractAdaptor.main(new HelloWorldConnector(), args);
-    }  
-}   
+  }
+
+  @Override
+  public void getModifiedDocIds(DocIdPusher pusher) throws IOException,
+      InterruptedException {
+    ArrayList<DocId> mockDocIds = new ArrayList<DocId>();
+    mockDocIds.add(new DocId("1002"));
+    pusher.pushDocIds(mockDocIds);
+  }
+
+  /** Call default main for adaptors. */
+  public static void main(String[] args) {
+    AbstractAdaptor.main(new HelloWorldConnector(), args);
+  }
+}
diff --git a/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/MetadataAddition.java b/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/MetadataAddition.java
index edd91b1..8541998 100644
--- a/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/MetadataAddition.java
+++ b/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/MetadataAddition.java
@@ -1,3 +1,5 @@
+package com.google.enterprise.adaptor.examples.HelloWorldConnector;
+
 // Copyright 2014 Google Inc. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -29,7 +31,7 @@
 public class MetadataAddition implements DocumentTransform {
   private static final Logger log = Logger.getLogger(MetadataAddition.class
       .getName());
-  private static String metaTaste = "taste";
+  private static final String META_TASTE = "taste";
   private Set<String> valuesToAdd = null;
 
   private MetadataAddition(String values) {
@@ -42,19 +44,19 @@
 
   /** Makes transform from config file with "taste". */
   public static MetadataAddition load(Map<String, String> cfg) {
-    return new MetadataAddition(cfg.get(metaTaste));
+    return new MetadataAddition(cfg.get(META_TASTE));
   }
 
   @Override
   public void transform(Metadata metadata, Map<String, String> params) {
-    Set<String> values = metadata.getAllValues(metaTaste);
+    Set<String> values = metadata.getAllValues(META_TASTE);
     if (values.isEmpty()) {
-      log.log(Level.INFO, "no metadata {0}. Skipping", metaTaste);
+      log.log(Level.INFO, "no metadata {0}. Skipping", META_TASTE);
     } else {
       log.log(Level.INFO,
               "adding values {1} for existing metadata {0}  ",
-              new Object[] { metaTaste, valuesToAdd });      
-      metadata.set(metaTaste, combine(values, valuesToAdd));
+              new Object[] { META_TASTE, valuesToAdd });
+      metadata.set(META_TASTE, combine(values, valuesToAdd));
     }
   }
 
@@ -66,6 +68,6 @@
 
   @Override
   public String toString() {
-    return "MetadataAddition(meta_taste=" + metaTaste + ")";
+    return "MetadataAddition(meta_taste=" + META_TASTE + ")";
   }
 }
diff --git a/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/MyAuthnIdentity.java b/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/MyAuthnIdentity.java
index 7e721a9..1243488 100644
--- a/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/MyAuthnIdentity.java
+++ b/src/com/google/enterprise/adaptor/examples/HelloWorldConnector/MyAuthnIdentity.java
@@ -1,3 +1,5 @@
+package com.google.enterprise.adaptor.examples.HelloWorldConnector;
+
 // Copyright 2014 Google Inc. All Rights Reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,22 +18,37 @@
 import com.google.enterprise.adaptor.GroupPrincipal;
 import com.google.enterprise.adaptor.UserPrincipal;
 
+import java.util.Collection;
 import java.util.Set;
+import java.util.TreeSet;
 
 /**
  * Stub of AuthnIdentity
  */
 public class MyAuthnIdentity implements AuthnIdentity {
 
-  UserPrincipal user;
-  Set<GroupPrincipal> groups;
+  private UserPrincipal user;
+  private Set<GroupPrincipal> groups;
 
-  public void setGroups(Set<GroupPrincipal> groups) {
-    this.groups = groups;
+  // Constructor  with user only
+  public MyAuthnIdentity(String uid) {
+    this.user = new UserPrincipal(uid);
   }
 
-  public void setUser(UserPrincipal user) {
-    this.user = user;
+  //Constructor with user & single group
+  public MyAuthnIdentity(String uid, String gid) {
+    this.user = new UserPrincipal(uid);
+    this.groups = new TreeSet<GroupPrincipal>();
+    this.groups.add(new GroupPrincipal(gid));
+  }
+
+  // Constructor with user & groups
+  public MyAuthnIdentity(String uid, Collection<String> gids) {
+    this.user = new UserPrincipal(uid);
+    this.groups = new TreeSet<GroupPrincipal>();
+    for (String n : gids) {
+      this.groups.add(new GroupPrincipal(n));
+    }
   }
 
   @Override