Add Startup exception to Adaptor init for permanent failure scenarios
Code Review : https://codereview.appspot.com/95310044/
diff --git a/src/com/google/enterprise/adaptor/sharepoint/SharePointAdaptor.java b/src/com/google/enterprise/adaptor/sharepoint/SharePointAdaptor.java
index 06e03fb..bc4cd0d 100644
--- a/src/com/google/enterprise/adaptor/sharepoint/SharePointAdaptor.java
+++ b/src/com/google/enterprise/adaptor/sharepoint/SharePointAdaptor.java
@@ -28,10 +28,12 @@
import com.google.enterprise.adaptor.DocIdPusher;
import com.google.enterprise.adaptor.GroupPrincipal;
import com.google.enterprise.adaptor.IOHelper;
+import com.google.enterprise.adaptor.InvalidConfigurationException;
import com.google.enterprise.adaptor.PollingIncrementalLister;
import com.google.enterprise.adaptor.Principal;
import com.google.enterprise.adaptor.Request;
import com.google.enterprise.adaptor.Response;
+import com.google.enterprise.adaptor.StartupException;
import com.google.enterprise.adaptor.UserPrincipal;
import com.google.enterprise.adaptor.sharepoint.RareModificationCache.CachedList;
import com.google.enterprise.adaptor.sharepoint.RareModificationCache.CachedVirtualServer;
@@ -88,6 +90,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.Authenticator;
+import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.URI;
@@ -511,20 +514,31 @@
URL virtualServerUrl = new URL(virtualServer);
ntlmAuthenticator.addPermitForHost(virtualServerUrl);
scheduledExecutor = new ScheduledThreadPoolExecutor(1);
-
-
+ String authenticationType;
if (useLiveAuthentication) {
+ if ("".equals(username) || "".equals(password)) {
+ throw new InvalidConfigurationException("Adaptor is configured to "
+ + "use Live authentication. Please specify valid username "
+ + "and password.");
+ }
SamlHandshakeManager manager = authenticationClientFactory
.newLiveAuthentication(virtualServer, username, password);
authenticationHandler = new SamlAuthenticationHandler.Builder(username,
password, scheduledExecutor, manager).build();
+ authenticationType = "Live";
} else if (!"".equals(stsendpoint) && !"".equals(stsrealm)) {
+ if ("".equals(username) || "".equals(password)) {
+ throw new InvalidConfigurationException("Adaptor is configured to "
+ + "use ADFS authentication. Please specify valid username "
+ + "and password.");
+ }
SamlHandshakeManager manager = authenticationClientFactory
.newAdfsAuthentication(virtualServer, username, password, stsendpoint,
stsrealm, config.getValue("sharepoint.sts.login"),
config.getValue("sharepoint.sts.trustLocation"));
authenticationHandler = new SamlAuthenticationHandler.Builder(username,
password, scheduledExecutor, manager).build();
+ authenticationType = "ADFS";
} else {
AuthenticationSoap authenticationSoap = authenticationClientFactory
.newSharePointFormsAuthentication(virtualServer, username, password);
@@ -532,10 +546,35 @@
authenticationHandler = new SharePointFormsAuthenticationHandler
.Builder(username, password, scheduledExecutor, authenticationSoap)
.build();
+ authenticationType = "SharePoint";
+ }
+
+ try {
+ log.log(Level.INFO, "Using {0} authentication.", authenticationType);
+ authenticationHandler.start();
+ } catch (IOException ex) {
+ if (ex instanceof UnknownHostException) {
+ // This may be due to DNS issue or transiant network error.
+ // Just rethrow excption and allow adaptor to retry.
+ throw ex;
+ }
+
+ if (ex instanceof ConnectException) {
+ // SharePoint might be down. Just rethrow exception and allow adaptor to
+ // retry.
+ throw ex;
+ }
+ String adfsWarning = "ADFS".equals(authenticationType)
+ ? " Also verify if stsendpoint and stsrealm is specified correctly "
+ + "and ADFS environment is available." : "";
+ String warning = String.format(
+ "Failed to start adaptor using %s authentication."
+ + " Please verify adaptor configuration for SharePoint url,"
+ + " username and password.%s", authenticationType, adfsWarning);
+ throw new StartupException(warning, ex);
}
try {
- authenticationHandler.start();
executor = executorFactory.call();
SiteAdaptor vsAdaptor = getSiteAdaptor(virtualServer, virtualServer);
SiteDataClient virtualServerSiteDataClient =
diff --git a/src/com/google/enterprise/adaptor/sharepoint/SharePointUserProfileAdaptor.java b/src/com/google/enterprise/adaptor/sharepoint/SharePointUserProfileAdaptor.java
index db23326..31034b2 100644
--- a/src/com/google/enterprise/adaptor/sharepoint/SharePointUserProfileAdaptor.java
+++ b/src/com/google/enterprise/adaptor/sharepoint/SharePointUserProfileAdaptor.java
@@ -23,9 +23,11 @@
import com.google.enterprise.adaptor.DocId;
import com.google.enterprise.adaptor.DocIdPusher;
import com.google.enterprise.adaptor.GroupPrincipal;
+import com.google.enterprise.adaptor.InvalidConfigurationException;
import com.google.enterprise.adaptor.PollingIncrementalLister;
import com.google.enterprise.adaptor.Request;
import com.google.enterprise.adaptor.Response;
+import com.google.enterprise.adaptor.StartupException;
import com.google.enterprise.adaptor.sharepoint.SamlAuthenticationHandler.SamlHandshakeManager;
import com.microsoft.schemas.sharepoint.soap.authentication.AuthenticationSoap;
@@ -56,10 +58,12 @@
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.Authenticator;
+import java.net.ConnectException;
import java.net.PasswordAuthentication;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
+import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.rmi.RemoteException;
import java.text.MessageFormat;
@@ -217,7 +221,7 @@
}
@Override
- public void init(AdaptorContext context) throws IOException {
+ public void init(AdaptorContext context) throws Exception {
context.setPollingIncrementalLister(this);
Config config = context.getConfig();
@@ -265,18 +269,31 @@
// Unfortunately, this is a JVM-wide modification.
Authenticator.setDefault(ntlmAuthenticator);
+ String authenticationType;
if (useLiveAuthentication) {
+ if ("".equals(username) || "".equals(password)) {
+ throw new InvalidConfigurationException("Adaptor is configured to "
+ + "use Live authentication. Please specify valid username "
+ + "and password.");
+ }
SamlHandshakeManager manager = authenticationClientFactory
.newLiveAuthentication(virtualServer, username, password);
authenticationHandler = new SamlAuthenticationHandler.Builder(username,
password, scheduledExecutor, manager).build();
+ authenticationType = "Live";
} else if (!"".equals(stsendpoint) && !"".equals(stsrealm)) {
+ if ("".equals(username) || "".equals(password)) {
+ throw new InvalidConfigurationException("Adaptor is configured to "
+ + "use ADFS authentication. Please specify valid username "
+ + "and password.");
+ }
SamlHandshakeManager manager = authenticationClientFactory
.newAdfsAuthentication(virtualServer, username, password, stsendpoint,
stsrealm, config.getValue("sharepoint.sts.login"),
config.getValue("sharepoint.sts.trustLocation"));
authenticationHandler = new SamlAuthenticationHandler.Builder(username,
password, scheduledExecutor, manager).build();
+ authenticationType = "ADFS";
} else {
AuthenticationSoap authenticationSoap = authenticationClientFactory
.newSharePointFormsAuthentication(virtualServer, username, password);
@@ -284,8 +301,33 @@
authenticationHandler = new SharePointFormsAuthenticationHandler
.Builder(username, password, scheduledExecutor, authenticationSoap)
.build();
+ authenticationType = "SharePoint";
}
- authenticationHandler.start();
+
+ try {
+ log.log(Level.INFO, "Using {0} authentication.", authenticationType);
+ authenticationHandler.start();
+ } catch (IOException ex) {
+ if (ex instanceof UnknownHostException) {
+ // This may be due to DNS issue or transiant network error.
+ // Just rethrow excption and allow adaptor to retry.
+ throw ex;
+ }
+
+ if (ex instanceof ConnectException) {
+ // SharePoint might be down. Just rethrow exception and allow adaptor to
+ // retry.
+ throw ex;
+ }
+ String adfsWarning = "ADFS".equals(authenticationType)
+ ? " Also verify if stsendpoint and stsrealm is specified correctly "
+ + "and ADFS environment is available." : "";
+ String warning = String.format(
+ "Failed to start adaptor using %s authentication."
+ + " Please verify adaptor configuration for SharePoint url,"
+ + " username and password.%s", authenticationType, adfsWarning);
+ throw new StartupException(warning, ex);
+ }
log.log(Level.FINEST, "Initializing User profile Service Client for {0}",
virtualServer + USER_PROFILE_SERVICE_ENDPOINT);
userProfileServiceClient = new UserProfileServiceClient(
diff --git a/test/com/google/enterprise/adaptor/sharepoint/SharePointAdaptorTest.java b/test/com/google/enterprise/adaptor/sharepoint/SharePointAdaptorTest.java
index d5cd8e3..ecc512a 100644
--- a/test/com/google/enterprise/adaptor/sharepoint/SharePointAdaptorTest.java
+++ b/test/com/google/enterprise/adaptor/sharepoint/SharePointAdaptorTest.java
@@ -32,6 +32,7 @@
import com.google.enterprise.adaptor.DocIdPusher;
import com.google.enterprise.adaptor.GroupPrincipal;
import com.google.enterprise.adaptor.IOHelper;
+import com.google.enterprise.adaptor.InvalidConfigurationException;
import com.google.enterprise.adaptor.Metadata;
import com.google.enterprise.adaptor.Principal;
import com.google.enterprise.adaptor.UserPrincipal;
@@ -102,6 +103,7 @@
import java.math.BigInteger;
import java.net.URI;
import java.net.URL;
+import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
@@ -421,6 +423,68 @@
}
@Test
+ public void testAdaptorInitAdfsUnknownHostException() throws Exception {
+ SoapFactory siteDataFactory = MockSoapFactory.blank()
+ .endpoint(VS_ENDPOINT, MockSiteData.blank()
+ .register(VS_CONTENT_EXCHANGE)
+ .register(CD_CONTENT_EXCHANGE))
+ .endpoint("http://localhost:1/_vti_bin/People.asmx",
+ new MockPeopleSoap())
+ .endpoint("http://localhost:1/_vti_bin/UserGroup.asmx",
+ new MockUserGroupSoap(null));
+ final MockSamlHandshakeManager samlManager
+ = new MockSamlHandshakeManager("token", "cookie") {
+ @Override
+ public String requestToken() throws IOException{
+ throw new UnknownHostException("stsendpoint");
+ }
+ };
+ adaptor = new SharePointAdaptor(siteDataFactory,
+ new UnsupportedHttpClient(), executorFactory,
+ new MockAuthenticationClientFactoryAdfs() {
+ @Override
+ public SamlHandshakeManager newAdfsAuthentication(
+ String virtualServer, String username, String password,
+ String stsendpoint, String stsrelam, String login,
+ String trustlocation) throws IOException {
+ return samlManager;
+ }
+ });
+ config.overrideKey("sharepoint.sts.endpoint", "https://stsendpoint");
+ config.overrideKey("sharepoint.sts.realm", "urn:sharepoint:com");
+ thrown.expect(IOException.class);
+ adaptor.init(new MockAdaptorContext(config, pusher));
+ adaptor = null;
+ }
+
+ @Test
+ public void testAdaptorInitAdfsWithBlankUsername() throws Exception {
+ adaptor = new SharePointAdaptor(initableSoapFactory,
+ new UnsupportedHttpClient(), executorFactory,
+ new MockAuthenticationClientFactoryForms());
+ config.overrideKey("sharepoint.sts.endpoint", "https://stsendpoint");
+ config.overrideKey("sharepoint.sts.realm", "urn:sharepoint:com");
+ config.overrideKey("sharepoint.usernamet", "");
+ config.overrideKey("sharepoint.password", "");
+ thrown.expect(InvalidConfigurationException.class);
+ adaptor.init(new MockAdaptorContext(config, pusher));
+ adaptor = null;
+ }
+
+ @Test
+ public void testAdaptorInitLiveWithBlankUsername() throws Exception {
+ adaptor = new SharePointAdaptor(initableSoapFactory,
+ new UnsupportedHttpClient(), executorFactory,
+ new MockAuthenticationClientFactoryForms());
+ config.overrideKey("sharepoint.useLiveAuthentication", "true");
+ config.overrideKey("sharepoint.usernamet", "");
+ config.overrideKey("sharepoint.password", "");
+ thrown.expect(InvalidConfigurationException.class);
+ adaptor.init(new MockAdaptorContext(config, pusher));
+ adaptor = null;
+ }
+
+ @Test
public void testAdaptorInitWithMissingRelam() throws Exception {
SoapFactory siteDataFactory = MockSoapFactory.blank()
.endpoint(VS_ENDPOINT, MockSiteData.blank()
@@ -3071,7 +3135,7 @@
}
@Override
- public String requestToken() {
+ public String requestToken() throws IOException {
return token;
}
diff --git a/test/com/google/enterprise/adaptor/sharepoint/SharePointUserProfileAdaptorTest.java b/test/com/google/enterprise/adaptor/sharepoint/SharePointUserProfileAdaptorTest.java
index 5df3fc0..d559698 100644
--- a/test/com/google/enterprise/adaptor/sharepoint/SharePointUserProfileAdaptorTest.java
+++ b/test/com/google/enterprise/adaptor/sharepoint/SharePointUserProfileAdaptorTest.java
@@ -24,6 +24,7 @@
import com.google.enterprise.adaptor.Config;
import com.google.enterprise.adaptor.DocId;
import com.google.enterprise.adaptor.GroupPrincipal;
+import com.google.enterprise.adaptor.InvalidConfigurationException;
import com.google.enterprise.adaptor.sharepoint.SamlAuthenticationHandler.SamlHandshakeManager;
import com.google.enterprise.adaptor.sharepoint.SharePointUserProfileAdaptor.UserProfileServiceClient;
@@ -48,7 +49,9 @@
import org.junit.Assume;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.w3c.dom.DOMImplementation;
@@ -82,6 +85,8 @@
private final Charset charset = Charset.forName("UTF-8");
private AuthenticationClientFactory authenticationFactory
= new MockAuthenticationClientFactoryForms();
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
@Before
public void setup() {
@@ -124,9 +129,22 @@
SharePointUserProfileAdaptor adaptor = new SharePointUserProfileAdaptor();
adaptor.destroy();
}
+
+ @Test
+ public void testAdaptorInitWithLive() throws Exception {
+ AccumulatingDocIdPusher pusher = new AccumulatingDocIdPusher();
+ adaptor = new SharePointUserProfileAdaptor(
+ new MockUserProfileServiceFactoryImpl(null), authenticationFactory);
+ config.overrideKey("sharepoint.useLiveAuthentication", "true");
+ config.overrideKey("sharepoint.usernamet", "");
+ config.overrideKey("sharepoint.password", "");
+ thrown.expect(InvalidConfigurationException.class);
+ adaptor.init(new MockAdaptorContext(config, pusher));
+ adaptor = null;
+ }
@Test
- public void testBlankCredentialsOnWindows() throws IOException {
+ public void testBlankCredentialsOnWindows() throws Exception {
Assume.assumeTrue(System.getProperty("os.name").contains("Windows"));
Config adaptorConfig = new Config();
new SharePointUserProfileAdaptor().initConfig(adaptorConfig);
@@ -143,7 +161,7 @@
}
@Test
- public void testGetDocIds() throws IOException, InterruptedException {
+ public void testGetDocIds() throws Exception {
MockUserProfileServiceFactoryImpl serviceFactory =
new MockUserProfileServiceFactoryImpl(null);
ArrayOfPropertyData profile = new ArrayOfPropertyData();
@@ -178,8 +196,7 @@
}
@Test
- public void testGetDocIdsNoProfiles()
- throws IOException, InterruptedException {
+ public void testGetDocIdsNoProfiles() throws Exception {
MockUserProfileServiceFactoryImpl serviceFactory =
new MockUserProfileServiceFactoryImpl(null);
adaptor = new SharePointUserProfileAdaptor(serviceFactory,
@@ -315,7 +332,7 @@
}
@Test
- public void testGetDocContentNotFound() throws IOException {
+ public void testGetDocContentNotFound() throws Exception {
MockUserProfileServiceFactoryImpl serviceFactory =
new MockUserProfileServiceFactoryImpl(null);
adaptor = new SharePointUserProfileAdaptor(serviceFactory,
@@ -333,7 +350,7 @@
}
@Test
- public void testGetDocContentInvalidDocId() throws IOException {
+ public void testGetDocContentInvalidDocId() throws Exception {
MockUserProfileServiceFactoryImpl serviceFactory =
new MockUserProfileServiceFactoryImpl(null);
ArrayOfPropertyData profile = new ArrayOfPropertyData();
@@ -356,8 +373,7 @@
}
@Test
- public void testGetModifiedDocIdsWithEmptyChangeToken()
- throws InterruptedException, IOException {
+ public void testGetModifiedDocIdsWithEmptyChangeToken() throws Exception {
MockUserProfileServiceFactoryImpl serviceFactory =
new MockUserProfileServiceFactoryImpl(
"change token on mock repository");
@@ -374,8 +390,7 @@
}
@Test
- public void testGetModifiedDocIdsWithNoChange()
- throws InterruptedException, IOException {
+ public void testGetModifiedDocIdsWithNoChange() throws Exception {
MockUserProfileServiceFactoryImpl serviceFactory =
new MockUserProfileServiceFactoryImpl(
"same current token");
@@ -392,8 +407,7 @@
}
@Test
- public void testGetModifiedDocIdsDiffrentTokenNoChange()
- throws InterruptedException, IOException {
+ public void testGetModifiedDocIdsDiffrentTokenNoChange() throws Exception {
MockUserProfileServiceFactoryImpl serviceFactory =
new MockUserProfileServiceFactoryImpl(
"new token");
@@ -410,8 +424,7 @@
}
@Test
- public void testGetModifiedDocIdsWithChange()
- throws InterruptedException, IOException {
+ public void testGetModifiedDocIdsWithChange() throws Exception {
MockUserProfileServiceFactoryImpl serviceFactory =
new MockUserProfileServiceFactoryImpl(
"new token");
@@ -448,8 +461,7 @@
}
@Test
- public void testGetModifiedDocIdsInvalidToken()
- throws InterruptedException, IOException {
+ public void testGetModifiedDocIdsInvalidToken()throws Exception {
MockUserProfileServiceFactoryImpl serviceFactory =
new MockUserProfileServiceFactoryImpl(
"sp token");