Merge branch 'master' of https://code.google.com/p/plexi
diff --git a/src/com/google/enterprise/adaptor/Config.java b/src/com/google/enterprise/adaptor/Config.java
index 5be02d8..4382353 100644
--- a/src/com/google/enterprise/adaptor/Config.java
+++ b/src/com/google/enterprise/adaptor/Config.java
@@ -52,6 +52,9 @@
  *      If not set, then an attempt to compute from gsa.version is made.
  *      Defaults to true for 7.2.0-0 and later, and false for earlier,
  *      as defined by gsa.version.
+ * <tr><td> </td><td>adaptor.markAllDocsAsPublic </td><td> Tells GSA all
+        documents are public.  Overrides all ACLs and even the setting of
+        {@code Response.setSecure()}.  Defaults to false
  * <tr><td> </td><td>adaptor.fullListingSchedule </td><td> when to invoke 
  *     {@link Adaptor#getDocIds Adaptor.getDocIds}, in cron format (minute,
  *     hour,  day of month, month, day of week).  Defaults to 0 3 * * *
@@ -99,7 +102,7 @@
  *     Defaults to true
  * <tr><td> </td><td>gsa.scoringType</td><td> type of relevance algorithm
  *      GSA utilizes to rank documents.  Either content or web.  Is sent
- *      when adaptor.sendDocControlHeader is true.  Defaults to content
+ *      when gsa.acceptsDocControlsHeader is true.  Defaults to content
  * <tr><td> </td><td>server.dashboardPort </td><td> port on adaptor's
  *     machine for accessing adaptor's dashboard.   Defaults to  5679
  * <tr><td> </td><td>server.docIdPath </td><td> part of URL preceding
@@ -251,6 +254,7 @@
             }
           }
         });
+    addKey("adaptor.markAllDocsAsPublic", "false");
   }
 
   public Set<String> getAllKeys() {
@@ -437,6 +441,14 @@
   }
 
   /**
+   * Whether adaptor tells GSA all documents are public, regardless of their
+   * ACLs. Defaults to {@code false}.
+   */
+  boolean markAllDocsAsPublic() {
+    return Boolean.parseBoolean(getValue("adaptor.markAllDocsAsPublic"));
+  }
+
+  /**
    * Cron-style format for describing when the adaptor should perform full
    * listings of {@code DocId}s. Multiple times can be specified by separating
    * them with a '|' (vertical bar).
@@ -687,7 +699,7 @@
       }
     }
     if (unset.size() != 0) {
-      throw new IllegalStateException("Missing configuration values: " + unset);
+      throw new InvalidConfigurationException("Missing configuration values: " + unset);
     }
   }
 
@@ -701,7 +713,7 @@
   public String getRawValue(String key) {
     String value = config.getProperty(key);
     if (value == null) {
-      throw new IllegalStateException(MessageFormat.format(
+      throw new InvalidConfigurationException(MessageFormat.format(
           "You must set configuration key ''{0}''.", key));
     }
     return value;
diff --git a/src/com/google/enterprise/adaptor/DocumentHandler.java b/src/com/google/enterprise/adaptor/DocumentHandler.java
index ac6c62e..0dad85c 100644
--- a/src/com/google/enterprise/adaptor/DocumentHandler.java
+++ b/src/com/google/enterprise/adaptor/DocumentHandler.java
@@ -79,6 +79,7 @@
   private final AclTransform aclTransform;
   private final boolean useCompression;
   private final boolean sendDocControls;
+  private final boolean markDocsPublic;
   private final long headerTimeoutMillis;
   private final long contentTimeoutMillis;
   private final String scoring;
@@ -94,7 +95,8 @@
                          TransformPipeline transform, AclTransform aclTransform,
                          boolean useCompression,
                          Watchdog watchdog, AsyncPusher pusher,
-                         boolean sendDocControls, long headerTimeoutMillis,
+                         boolean sendDocControls, boolean markDocsPublic,
+                         long headerTimeoutMillis,
                          long contentTimeoutMillis, String scoringType) {
     if (docIdDecoder == null || docIdEncoder == null || journal == null
         || adaptor == null || aclTransform == null || watchdog == null
@@ -113,6 +115,7 @@
     this.watchdog = watchdog;
     this.pusher = pusher;
     this.sendDocControls = sendDocControls;
+    this.markDocsPublic = markDocsPublic;
     this.headerTimeoutMillis = headerTimeoutMillis;
     this.contentTimeoutMillis = contentTimeoutMillis;
     this.scoring = scoringType;
@@ -796,7 +799,12 @@
       if (transform != null) {
         transform();  
       } 
-      acl = aclTransform.transform(acl);
+      if (markDocsPublic) {
+        acl = null;
+        secure = false;
+      } else {
+        acl = aclTransform.transform(acl);
+      }
       if (requestIsFromFullyTrustedClient(ex)) {
         // Always specify metadata and ACLs, even when empty, to replace
         // previous values.
diff --git a/src/com/google/enterprise/adaptor/GsaCommunicationHandler.java b/src/com/google/enterprise/adaptor/GsaCommunicationHandler.java
index 5ee89f2..2adf482 100644
--- a/src/com/google/enterprise/adaptor/GsaCommunicationHandler.java
+++ b/src/com/google/enterprise/adaptor/GsaCommunicationHandler.java
@@ -294,6 +294,7 @@
         config.isServerToUseCompression(), watchdog,
         asyncDocIdSender, 
         config.doesGsaAcceptDocControlsHeader(),
+        config.markAllDocsAsPublic(),
         config.getAdaptorDocHeaderTimeoutMillis(),
         config.getAdaptorDocContentTimeoutMillis(),
         config.getScoringType());
diff --git a/src/com/google/enterprise/adaptor/StartupException.java b/src/com/google/enterprise/adaptor/StartupException.java
index 6ef7673..c8b5d3a 100644
--- a/src/com/google/enterprise/adaptor/StartupException.java
+++ b/src/com/google/enterprise/adaptor/StartupException.java
@@ -20,7 +20,7 @@
  * the retry with back-off recovery logic and immediately terminate the
  * adaptor.
  */
-public class StartupException extends Exception {
+public class StartupException extends RuntimeException {
   /**
    * Constructs a new StartupException with no message and no root
    * cause.
diff --git a/test/com/google/enterprise/adaptor/ApplicationTest.java b/test/com/google/enterprise/adaptor/ApplicationTest.java
index 871afba..c5ebb10 100644
--- a/test/com/google/enterprise/adaptor/ApplicationTest.java
+++ b/test/com/google/enterprise/adaptor/ApplicationTest.java
@@ -89,7 +89,7 @@
   public void testConfigFileOverrideArgumentParse() {
     config = new ModifiedConfig();
     configFile.setFileContents("gsa.hostname=notreal\n");
-    thrown.expect(java.lang.IllegalStateException.class);
+    thrown.expect(InvalidConfigurationException.class);
     // provide config file name and above config isn't read; validate fails
     Application.autoConfig(config, new String[] {"-Dadaptor.configfile=NFE"},
         configFile);
diff --git a/test/com/google/enterprise/adaptor/ConfigTest.java b/test/com/google/enterprise/adaptor/ConfigTest.java
index bc9d5a6..4556a9f 100644
--- a/test/com/google/enterprise/adaptor/ConfigTest.java
+++ b/test/com/google/enterprise/adaptor/ConfigTest.java
@@ -44,7 +44,7 @@
   @Test
   public void testNoInputLoad() {
     // Requires gsa.hostname to be set
-    thrown.expect(IllegalStateException.class);
+    thrown.expect(InvalidConfigurationException.class);
     config.validate();
   }
 
diff --git a/test/com/google/enterprise/adaptor/DocumentHandlerTest.java b/test/com/google/enterprise/adaptor/DocumentHandlerTest.java
index a30e72f..57d442a 100644
--- a/test/com/google/enterprise/adaptor/DocumentHandlerTest.java
+++ b/test/com/google/enterprise/adaptor/DocumentHandlerTest.java
@@ -1165,6 +1165,84 @@
   }
 
   @Test
+  public void testMarkPublicOverridesAclDocControlsVersion() throws Exception {
+    MockAdaptor adaptor = new MockAdaptor() {
+          @Override
+          public void getDocContent(Request request, Response response)
+              throws IOException {
+            response.setAcl(new Acl.Builder()
+                .setPermitUsers(Arrays.asList(
+                    new UserPrincipal("usr2"), new UserPrincipal("usr", "ns")))
+                .setInheritFrom(new DocId("testing")).build());
+            response.getOutputStream();
+          }
+        };
+    String remoteIp = ex.getRemoteAddress().getAddress().getHostAddress();
+    DocumentHandler handler = createHandlerBuilder()
+        .setAdaptor(adaptor)
+        .setMarkDocsPublic(true)
+        .setSendDocControls(true)
+        .setFullAccessHosts(new String[] {remoteIp})
+        .build();
+    handler.handle(ex);
+    assertEquals(200, ex.getResponseCode());
+    assertEquals("public",
+        ex.getResponseHeaders().getFirst("X-Gsa-Serve-Security"));
+    assertEquals("acl=",
+        ex.getResponseHeaders().get("X-Gsa-Doc-Controls").get(0));
+  }
+
+  @Test
+  public void testMarkPublicOverridesAclMetadataVersion() throws Exception {
+    MockAdaptor adaptor = new MockAdaptor() {
+          @Override
+          public void getDocContent(Request request, Response response)
+              throws IOException {
+            response.setAcl(new Acl.Builder()
+                .setPermitUsers(Arrays.asList(
+                    new UserPrincipal("usr2"), new UserPrincipal("usr", "ns")))
+                .setInheritFrom(new DocId("testing")).build());
+            response.getOutputStream();
+          }
+        };
+    String remoteIp = ex.getRemoteAddress().getAddress().getHostAddress();
+    DocumentHandler handler = createHandlerBuilder()
+        .setAdaptor(adaptor)
+        .setMarkDocsPublic(true)
+        .setFullAccessHosts(new String[] {remoteIp})
+        .build();
+    handler.handle(ex);
+    assertEquals(200, ex.getResponseCode());
+    assertEquals("public",
+        ex.getResponseHeaders().getFirst("X-Gsa-Serve-Security"));
+    assertEquals("",
+        ex.getResponseHeaders().get("X-Gsa-External-Metadata").get(0));
+  }
+
+  @Test
+  public void testMarkPublicOverridesExplicitSecure() throws Exception {
+    MockAdaptor adaptor = new MockAdaptor() {
+          @Override
+          public void getDocContent(Request request, Response response)
+              throws IOException {
+            response.setSecure(true);
+            response.getOutputStream();
+          }
+        };
+    String remoteIp = ex.getRemoteAddress().getAddress().getHostAddress();
+    DocumentHandler handler = createHandlerBuilder()
+        .setAdaptor(adaptor)
+        .setMarkDocsPublic(true)
+        .setSendDocControls(true)
+        .setFullAccessHosts(new String[] {remoteIp})
+        .build();
+    handler.handle(ex);
+    assertEquals(200, ex.getResponseCode());
+    assertEquals("public",
+        ex.getResponseHeaders().getFirst("X-Gsa-Serve-Security"));
+  }
+
+  @Test
   public void testEmulatedFields() throws Exception {
     String remoteIp = ex.getRemoteAddress().getAddress().getHostAddress();
     MockAdaptor adaptor = new MockAdaptor() {
@@ -1428,6 +1506,7 @@
     private Watchdog watchdog;
     private DocumentHandler.AsyncPusher pusher;
     private boolean sendDocControls;
+    private boolean markDocsPublic;
     private long headerTimeoutMillis = 30 * 1000;
     private long contentTimeoutMillis = 180 * 1000;
     private String scoring = "content";
@@ -1505,6 +1584,11 @@
       return this;
     }
 
+    public DocumentHandlerBuilder setMarkDocsPublic(boolean markDocsPublic) {
+      this.markDocsPublic = markDocsPublic;
+      return this;
+    }
+
     public DocumentHandlerBuilder setHeaderTimeoutMillis(
         long headerTimeoutMillis) {
       this.headerTimeoutMillis = headerTimeoutMillis;
@@ -1526,7 +1610,9 @@
       return new DocumentHandler(docIdDecoder, docIdEncoder, journal, adaptor,
           authzAuthority, gsaHostname, fullAccessHosts, samlServiceProvider,
           transform, aclTransform, useCompression, watchdog, pusher,
-          sendDocControls, headerTimeoutMillis, contentTimeoutMillis, scoring);
+          sendDocControls, markDocsPublic, headerTimeoutMillis,
+          contentTimeoutMillis, scoring);
     }
   }
 }
+