Allow the adaptor's entity ID to be overridden

This will be necessary when using authn or authz with multiple adaptors
simultaneously. In the future we may want to generate an entity ID based
on the hostname and port of the adaptor, but it isn't clear that is
worth the added confusion for the user.
diff --git a/src/com/google/enterprise/adaptor/Config.java b/src/com/google/enterprise/adaptor/Config.java
index d1f9f6b..a0b92a5 100644
--- a/src/com/google/enterprise/adaptor/Config.java
+++ b/src/com/google/enterprise/adaptor/Config.java
@@ -105,6 +105,9 @@
  * <tr><td> </td><td>server.reverseProxyProtocol </td><td> either http or https,
  *     depending on  proxy traffic.  Defaults to https in secure
  *     mode and http otherwise
+ * <tr><td> </td><td>server.samlEntityId </td><td> The SAML Entity ID that the
+ *     Adaptor will use to identity itself. Defaults to
+ *     http://google.com/enterprise/gsa/adaptor
  * <tr><td> </td><td>server.secure </td><td> enables https and certificate
  *     checking. Defaults to false
  * <tr><td> </td><td>server.useCompression </td><td> compress retrieval
@@ -184,6 +187,7 @@
     // for each request.
     addKey("server.queueCapacity", "160");
     addKey("server.useCompression", "true");
+    addKey("server.samlEntityId", "http://google.com/enterprise/gsa/adaptor");
     addKey("gsa.hostname", null);
     addKey("gsa.characterEncoding", "UTF-8");
     addKey("gsa.614FeedWorkaroundEnabled", "false");
@@ -400,6 +404,10 @@
     return Integer.parseInt(getValue("server.queueCapacity"));
   }
 
+  public String getServerSamlEntityId() {
+    return getValue("server.samlEntityId");
+  }
+
   public boolean isServerToUseCompression() {
     return Boolean.parseBoolean(getValue("server.useCompression"));
   }
diff --git a/src/com/google/enterprise/adaptor/GsaCommunicationHandler.java b/src/com/google/enterprise/adaptor/GsaCommunicationHandler.java
index 98f0b01..94d88d3 100644
--- a/src/com/google/enterprise/adaptor/GsaCommunicationHandler.java
+++ b/src/com/google/enterprise/adaptor/GsaCommunicationHandler.java
@@ -243,7 +243,7 @@
       bootstrapOpenSaml();
       SamlMetadata metadata = new SamlMetadata(config.getServerHostname(),
           config.getServerPort(), config.getGsaHostname(),
-          config.getGsaSamlEntityId());
+          config.getGsaSamlEntityId(), config.getServerSamlEntityId());
 
       if (adaptor instanceof AuthnAdaptor) {
         log.config("Adaptor is an AuthnAdaptor; enabling adaptor-based "
diff --git a/src/com/google/enterprise/adaptor/SamlMetadata.java b/src/com/google/enterprise/adaptor/SamlMetadata.java
index b544578..3b06f4d 100644
--- a/src/com/google/enterprise/adaptor/SamlMetadata.java
+++ b/src/com/google/enterprise/adaptor/SamlMetadata.java
@@ -42,15 +42,15 @@
       Configuration.getBuilderFactory();
 
   public SamlMetadata(String hostname, int port, String gsaHostname,
-      String gsaEntityId) {
-    localEntity = createLocalEntity(hostname, port);
+      String gsaEntityId, String adaptorEntityId) {
+    localEntity = createLocalEntity(hostname, port, adaptorEntityId);
     peerEntity = createPeerEntity(gsaHostname, gsaEntityId);
   }
 
-  private EntityDescriptor createLocalEntity(String hostname, int port) {
+  private EntityDescriptor createLocalEntity(String hostname, int port,
+      String adaptorEntityId) {
     EntityDescriptor ed = makeSamlObject(EntityDescriptor.DEFAULT_ELEMENT_NAME);
-    // TODO(ejona): It may be useful to make this instance-specific.
-    ed.setEntityID("http://google.com/enterprise/gsa/adaptor");
+    ed.setEntityID(adaptorEntityId);
 
     SPSSODescriptor spsso = makeSamlObject(
         SPSSODescriptor.DEFAULT_ELEMENT_NAME);
diff --git a/test/com/google/enterprise/adaptor/AuthnHandlerTest.java b/test/com/google/enterprise/adaptor/AuthnHandlerTest.java
index 96dae14..5080b71 100644
--- a/test/com/google/enterprise/adaptor/AuthnHandlerTest.java
+++ b/test/com/google/enterprise/adaptor/AuthnHandlerTest.java
@@ -44,7 +44,8 @@
       = new SessionManager<HttpExchange>(new MockTimeProvider(),
           new SessionManager.HttpExchangeClientStore(), 1000, 1000);
   private SamlMetadata metadata = new SamlMetadata("localhost", 80,
-      "thegsa", "http://google.com/enterprise/gsa/security-manager");
+      "thegsa", "http://google.com/enterprise/gsa/security-manager",
+      "http://google.com/enterprise/gsa/adaptor");
   private HttpClientAdapter httpClient = new HttpClientAdapter();
   private AuthnHandler handler = new AuthnHandler(sessionManager, metadata,
       httpClient, null);
diff --git a/test/com/google/enterprise/adaptor/SamlAssertionConsumerHandlerTest.java b/test/com/google/enterprise/adaptor/SamlAssertionConsumerHandlerTest.java
index bb62598..122ce41 100644
--- a/test/com/google/enterprise/adaptor/SamlAssertionConsumerHandlerTest.java
+++ b/test/com/google/enterprise/adaptor/SamlAssertionConsumerHandlerTest.java
@@ -39,7 +39,8 @@
       = new SessionManager<HttpExchange>(new MockTimeProvider(),
           new SessionManager.HttpExchangeClientStore(), 1000, 1000);
   private SamlMetadata metadata = new SamlMetadata("localhost", 80,
-      "thegsa", "http://google.com/enterprise/gsa/security-manager");
+      "thegsa", "http://google.com/enterprise/gsa/security-manager",
+      "http://google.com/enterprise/gsa/adaptor");
   private SamlAssertionConsumerHandler handler
       = new SamlAssertionConsumerHandler(sessionManager);
   private MockHttpExchange ex
diff --git a/test/com/google/enterprise/adaptor/SamlBatchAuthzHandlerTest.java b/test/com/google/enterprise/adaptor/SamlBatchAuthzHandlerTest.java
index a855cb9..49e1885 100644
--- a/test/com/google/enterprise/adaptor/SamlBatchAuthzHandlerTest.java
+++ b/test/com/google/enterprise/adaptor/SamlBatchAuthzHandlerTest.java
@@ -37,7 +37,8 @@
 
   private MockAdaptor adaptor = new MockAdaptor();
   private SamlMetadata samlMetadata = new SamlMetadata("localhost", 80,
-      "localhost", "http://google.com/enterprise/gsa/security-manager");
+      "localhost", "http://google.com/enterprise/gsa/security-manager",
+      "http://google.com/enterprise/gsa/adaptor");
   private SamlBatchAuthzHandler handler = new SamlBatchAuthzHandler(
       adaptor, new MockDocIdCodec(), samlMetadata);
   private MockHttpExchange ex = new MockHttpExchange("POST", "/",
diff --git a/test/com/google/enterprise/adaptor/SamlIdentityProviderTest.java b/test/com/google/enterprise/adaptor/SamlIdentityProviderTest.java
index 5259aea..4562ead 100644
--- a/test/com/google/enterprise/adaptor/SamlIdentityProviderTest.java
+++ b/test/com/google/enterprise/adaptor/SamlIdentityProviderTest.java
@@ -38,7 +38,8 @@
   private SamlMetadata metadata = new SamlMetadata(
       "bruteforce.mtv.corp.google.com", 5678,
       "entyo36.hot.corp.google.com",
-      "http://google.com/enterprise/gsa/security-manager");
+      "http://google.com/enterprise/gsa/security-manager",
+      "http://google.com/enterprise/gsa/adaptor");
   private UserPrincipal user = new UserPrincipal("user1");
   private Set<GroupPrincipal> groups = GroupPrincipal.makeSet(Arrays.asList(
       "group1", "group2"));