Merge branch 'master' of https://code.google.com/p/plexi.sharepoint
diff --git a/src/com/google/enterprise/adaptor/sharepoint/AuthenticationResult.java b/src/com/google/enterprise/adaptor/sharepoint/AuthenticationResult.java
new file mode 100644
index 0000000..0e86c0e
--- /dev/null
+++ b/src/com/google/enterprise/adaptor/sharepoint/AuthenticationResult.java
@@ -0,0 +1,44 @@
+// Copyright 2014 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.sharepoint;
+
+public class AuthenticationResult {
+ private final String cookie;
+ private final int cookieTimeOut;
+ private final String errorCode;
+
+ public AuthenticationResult(String cookie,
+ int cookieTimeOut, String errorCode) {
+ if (cookieTimeOut <= 0) {
+ throw new IllegalArgumentException();
+ }
+ this.cookie = cookie;
+ this.cookieTimeOut = cookieTimeOut;
+ this.errorCode = errorCode;
+ }
+
+ public String getCookie() {
+ return cookie;
+ }
+
+ public int getCookieTimeOut() {
+ return cookieTimeOut;
+ }
+
+ public String getErrorCode() {
+ return errorCode;
+ }
+}
diff --git a/src/com/google/enterprise/adaptor/sharepoint/FormsAuthenticationHandler.java b/src/com/google/enterprise/adaptor/sharepoint/FormsAuthenticationHandler.java
index 035dafc..a223818 100644
--- a/src/com/google/enterprise/adaptor/sharepoint/FormsAuthenticationHandler.java
+++ b/src/com/google/enterprise/adaptor/sharepoint/FormsAuthenticationHandler.java
@@ -16,24 +16,15 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
-import com.microsoft.schemas.sharepoint.soap.authentication.AuthenticationMode;
-import com.microsoft.schemas.sharepoint.soap.authentication.AuthenticationSoap;
-import com.microsoft.schemas.sharepoint.soap.authentication.LoginErrorCode;
-import com.microsoft.schemas.sharepoint.soap.authentication.LoginResult;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
-import javax.xml.ws.BindingProvider;
-import javax.xml.ws.WebServiceException;
-import javax.xml.ws.handler.MessageContext;
-
/**
* Helper class to handle forms authentication.
@@ -54,19 +45,19 @@
private final Runnable refreshRunnable = new RefreshRunnable();
private final List<String> authenticationCookiesList
= new CopyOnWriteArrayList<String>();
- private AuthenticationMode authenticationMode;
- private final AuthenticationSoap authenticationClient;
-
+ private final AuthenticationHandler authenticationClient;
+ private boolean isFormsAuthentication = false;
+
@VisibleForTesting
FormsAuthenticationHandler(String userName, String password,
ScheduledExecutorService executor,
- AuthenticationSoap authenticationClient) {
+ AuthenticationHandler authenticationClient) {
if (userName == null || password == null || executor == null ||
authenticationClient == null) {
throw new NullPointerException();
}
this.userName = userName;
- this.password = password;
+ this.password = password;
this.executor = executor;
this.authenticationClient = authenticationClient;
}
@@ -76,54 +67,38 @@
}
public boolean isFormsAuthentication() {
- return authenticationMode == AuthenticationMode.FORMS;
+ return isFormsAuthentication;
}
private void refreshCookies() throws IOException {
- log.log(Level.FINE, "AuthenticationMode = {0}", authenticationMode);
- if (authenticationMode != AuthenticationMode.FORMS) {
- return;
- }
if ("".equals(userName) || "".equals(password)) {
log.log(Level.FINE,
"Empty username / password. Using authentication mode as Windows");
- authenticationMode = AuthenticationMode.WINDOWS;
+ isFormsAuthentication = false;
return;
}
-
- LoginResult result;
- try {
- result = authenticationClient.login(userName, password);
- } catch (WebServiceException ex) {
- log.log(Level.WARNING,
- "Possible SP2013 environment with windows authentication", ex);
- authenticationMode = AuthenticationMode.WINDOWS;
+
+ if (!isFormsAuthentication) {
return;
}
- log.log(Level.FINE,
- "Login Cookie Expiration in = {0}", result.getTimeoutSeconds());
- if (result.getErrorCode() != LoginErrorCode.NO_ERROR) {
- log.log(Level.WARNING, "Forms authentication failed with authentication "
- + "web service with Error Code {0}. Possible SharePoint environment "
- + "with multiple claims provider. Adaptor might have been configured "
- + "to use windows authentication.", result.getErrorCode());
+
+ log.log(Level.FINE, "About to refresh authentication cookie.");
+ AuthenticationResult result = authenticationClient.authenticate();
+ log.log(Level.FINE, "Authentication Result {0}", result.getErrorCode());
+
+ String cookie = result.getCookie();
+ if (Strings.isNullOrEmpty(cookie)) {
+ log.log(Level.INFO, "Authentication cookie is null or empty."
+ + " Adaptor will use Windows authentication.");
return;
}
- @SuppressWarnings("unchecked")
- Map<String, Object> responseHeaders
- = (Map<String, Object>) ((BindingProvider) authenticationClient)
- .getResponseContext().get(MessageContext.HTTP_RESPONSE_HEADERS);
- log.log(Level.FINEST, "Response headers: {0}", responseHeaders);
- @SuppressWarnings("unchecked")
- String cookies = ((List<String>) responseHeaders.get("Set-cookie")).get(0);
if (authenticationCookiesList.isEmpty()) {
- authenticationCookiesList.add(cookies);
+ authenticationCookiesList.add(cookie);
} else {
- authenticationCookiesList.set(0, cookies);
+ authenticationCookiesList.set(0, cookie);
}
- long cookieTimeOut = (result.getTimeoutSeconds() == null) ?
- DEFAULT_COOKIE_TIMEOUT_SECONDS : result.getTimeoutSeconds();
+ long cookieTimeOut = result.getCookieTimeOut();
long rerunAfter = (cookieTimeOut + 1) / 2;
executor.schedule(refreshRunnable, rerunAfter, TimeUnit.SECONDS);
@@ -132,7 +107,13 @@
}
public void start() throws IOException {
- authenticationMode = authenticationClient.mode();
+ if ("".equals(userName) || "".equals(password)) {
+ log.log(Level.FINE, "Empty username or password. Using windows"
+ + " integrated authentication.");
+ isFormsAuthentication = false;
+ return;
+ }
+ isFormsAuthentication = authenticationClient.isFormsAuthentication();
refreshCookies();
}
@@ -148,4 +129,9 @@
}
}
}
-}
+
+ interface AuthenticationHandler {
+ AuthenticationResult authenticate() throws IOException;
+ boolean isFormsAuthentication() throws IOException;
+ }
+}
\ No newline at end of file
diff --git a/src/com/google/enterprise/adaptor/sharepoint/SharePointAdaptor.java b/src/com/google/enterprise/adaptor/sharepoint/SharePointAdaptor.java
index 4500ef4..22fc5eb 100644
--- a/src/com/google/enterprise/adaptor/sharepoint/SharePointAdaptor.java
+++ b/src/com/google/enterprise/adaptor/sharepoint/SharePointAdaptor.java
@@ -474,9 +474,12 @@
scheduledExecutor = new ScheduledThreadPoolExecutor(1);
String authenticationEndPoint = spUrlToUri(
virtualServer + "/_vti_bin/Authentication.asmx").toString();
+ SharePointFormsAuthenticationHandler authenticationClient
+ = new SharePointFormsAuthenticationHandler(
+ soapFactory.newAuthentication(authenticationEndPoint),
+ username, password);
authenticationHandler = new FormsAuthenticationHandler(username,
- password, scheduledExecutor,
- soapFactory.newAuthentication(authenticationEndPoint));
+ password, scheduledExecutor, authenticationClient);
authenticationHandler.start();
executor = executorFactory.call();
try {
diff --git a/src/com/google/enterprise/adaptor/sharepoint/SharePointFormsAuthenticationHandler.java b/src/com/google/enterprise/adaptor/sharepoint/SharePointFormsAuthenticationHandler.java
new file mode 100644
index 0000000..c3c9406
--- /dev/null
+++ b/src/com/google/enterprise/adaptor/sharepoint/SharePointFormsAuthenticationHandler.java
@@ -0,0 +1,131 @@
+// Copyright 2014 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.sharepoint;
+
+import com.google.enterprise.adaptor.sharepoint.FormsAuthenticationHandler.AuthenticationHandler;
+import com.microsoft.schemas.sharepoint.soap.authentication.AuthenticationMode;
+import com.microsoft.schemas.sharepoint.soap.authentication.AuthenticationSoap;
+import com.microsoft.schemas.sharepoint.soap.authentication.LoginErrorCode;
+import com.microsoft.schemas.sharepoint.soap.authentication.LoginResult;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.xml.ws.BindingProvider;
+import javax.xml.ws.WebServiceException;
+import javax.xml.ws.handler.MessageContext;
+
+/**
+ * AuthenticationHandler implementation for SharePoint forms authentication
+ * using Authentication.asmx web service.
+*/
+public class SharePointFormsAuthenticationHandler
+ implements AuthenticationHandler {
+ private static final Logger log
+ = Logger.getLogger(SharePointFormsAuthenticationHandler.class.getName());
+ // Default time out for forms authentication with .NET is 30 mins
+ private static final int DEFAULT_COOKIE_TIMEOUT_SECONDS = 30 * 60;
+ private final AuthenticationSoap authenticationClient;
+ private AuthenticationMode authenticationMode;
+ private final String username;
+ private final String password;
+
+ SharePointFormsAuthenticationHandler(AuthenticationSoap authenticationClient,
+ String username, String password) {
+ if (authenticationClient == null || username == null || password == null) {
+ throw new NullPointerException();
+ }
+ this.authenticationClient = authenticationClient;
+ this.username = username;
+ this.password = password;
+ }
+
+ public AuthenticationResult authenticate() throws IOException {
+ if (!isFormsAuthentication()) {
+ return new AuthenticationResult(null, DEFAULT_COOKIE_TIMEOUT_SECONDS,
+ LoginErrorCode.NOT_IN_FORMS_AUTHENTICATION_MODE.toString());
+ }
+ LoginResult result;
+ try {
+ result = authenticationClient.login(username, password);
+ } catch (WebServiceException ex) {
+ log.log(Level.WARNING,
+ "Forms authentication failed.", ex);
+ log.log(Level.INFO, "Possible SharePoint environment configured to use "
+ + "claims based windows integrated authentication. "
+ + "Adaptor will fallback to use windows integrated authentication.");
+ return new AuthenticationResult(null, DEFAULT_COOKIE_TIMEOUT_SECONDS,
+ LoginErrorCode.NOT_IN_FORMS_AUTHENTICATION_MODE.toString());
+ }
+
+ log.log(Level.FINE,
+ "Login Cookie Expiration in = {0}", result.getTimeoutSeconds());
+ if (result.getErrorCode() != LoginErrorCode.NO_ERROR) {
+ log.log(Level.WARNING, "Forms authentication failed with error code {0}. "
+ + "Possible SharePoint environment with multiple claims providers. "
+ + "Adaptor will fallback to use windows integrated authentication.",
+ result.getErrorCode());
+ return new AuthenticationResult(null, DEFAULT_COOKIE_TIMEOUT_SECONDS,
+ result.getErrorCode().toString());
+ }
+
+ @SuppressWarnings("unchecked")
+ Map<String, Object> responseHeaders
+ = (Map<String, Object>) ((BindingProvider) authenticationClient)
+ .getResponseContext().get(MessageContext.HTTP_RESPONSE_HEADERS);
+ log.log(Level.FINEST, "Response headers: {0}", responseHeaders);
+ if(!responseHeaders.containsKey("Set-cookie")) {
+ throw new IOException("Unable to extract authentication cookie.");
+ }
+
+ @SuppressWarnings("unchecked")
+ List<String> cookies = (List<String>) responseHeaders.get("Set-cookie");
+ if (cookies == null || cookies.isEmpty()) {
+ throw new IOException("Unable to extract authentication cookie.");
+ }
+
+ int cookieTimeout;
+ // On SP2007 result.getTimeoutSeconds() can be null
+ if (result.getTimeoutSeconds() == null) {
+ log.log(Level.FINE,
+ "Login cookie timeout is null. Using default cookie timeout.");
+ cookieTimeout = DEFAULT_COOKIE_TIMEOUT_SECONDS;
+ } else {
+ cookieTimeout = result.getTimeoutSeconds() > 0
+ ? result.getTimeoutSeconds() : DEFAULT_COOKIE_TIMEOUT_SECONDS;
+ }
+
+ log.log(Level.FINE,
+ "Login Cookie Expiration in = {0} seconds", cookieTimeout);
+
+ return new AuthenticationResult(cookies.get(0), cookieTimeout,
+ result.getErrorCode().toString());
+ }
+
+ public boolean isFormsAuthentication() throws IOException {
+ if (authenticationMode == null) {
+ // Cache authentication mode value to avoid repetitive web service
+ // calls to get authentication mode.
+ setAuthenticationMode(authenticationClient.mode());
+ log.log(Level.FINE, "Authentication Mode {0}", authenticationMode);
+ }
+ return authenticationMode == AuthenticationMode.FORMS;
+ }
+
+ private synchronized void setAuthenticationMode(AuthenticationMode mode) {
+ authenticationMode = mode;
+ }
+}
diff --git a/src/com/google/enterprise/adaptor/sharepoint/SharePointUserProfileAdaptor.java b/src/com/google/enterprise/adaptor/sharepoint/SharePointUserProfileAdaptor.java
index 5ff3932..c4e3b87 100644
--- a/src/com/google/enterprise/adaptor/sharepoint/SharePointUserProfileAdaptor.java
+++ b/src/com/google/enterprise/adaptor/sharepoint/SharePointUserProfileAdaptor.java
@@ -226,9 +226,13 @@
Authenticator.setDefault(ntlmAuthenticator);
String authenticationEndPoint
= virtualServer + "/_vti_bin/Authentication.asmx";
+ SharePointFormsAuthenticationHandler authenticationClient
+ = new SharePointFormsAuthenticationHandler(
+ userProfileServiceFactory.newAuthentication(authenticationEndPoint),
+ username, password);
FormsAuthenticationHandler authenticationHandler
= new FormsAuthenticationHandler(username, password, scheduledExecutor,
- userProfileServiceFactory.newAuthentication(authenticationEndPoint));
+ authenticationClient);
authenticationHandler.start();
log.log(Level.FINEST, "Initializing User profile Service Client for {0}",
virtualServer + USER_PROFILE_SERVICE_ENDPOINT);
diff --git a/test/com/google/enterprise/adaptor/sharepoint/FormsAuthenticationHandlerTest.java b/test/com/google/enterprise/adaptor/sharepoint/FormsAuthenticationHandlerTest.java
new file mode 100644
index 0000000..84ec9da
--- /dev/null
+++ b/test/com/google/enterprise/adaptor/sharepoint/FormsAuthenticationHandlerTest.java
@@ -0,0 +1,200 @@
+// Copyright 2014 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.sharepoint;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.enterprise.adaptor.sharepoint.FormsAuthenticationHandler.AuthenticationHandler;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+public class FormsAuthenticationHandlerTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ private static class UnsupportedAuthenticationHandler
+ implements AuthenticationHandler {
+
+ public AuthenticationResult authenticate() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isFormsAuthentication() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private static class MockAuthenticationHandler
+ extends UnsupportedAuthenticationHandler {
+
+ private boolean isFormsAuthentication;
+ private AuthenticationResult authenticationResult;
+
+ MockAuthenticationHandler(boolean isFormsAuthentication,
+ AuthenticationResult authenticationResult) {
+ this.isFormsAuthentication = isFormsAuthentication;
+ this.authenticationResult = authenticationResult;
+ }
+
+ @Override
+ public AuthenticationResult authenticate() throws IOException {
+ if (authenticationResult == null) {
+ throw new UnsupportedOperationException();
+ }
+ return authenticationResult;
+ }
+
+ @Override
+ public boolean isFormsAuthentication() throws IOException {
+ return isFormsAuthentication;
+ }
+ }
+
+ private static class UnsupportedScheduledExecutor extends CallerRunsExecutor
+ implements ScheduledExecutorService {
+
+ public ScheduledFuture<?> schedule(Runnable command, long delay,
+ TimeUnit unit) {
+ throw new UnsupportedOperationException();
+ }
+
+ public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay,
+ TimeUnit unit) {
+ throw new UnsupportedOperationException();
+ }
+
+ public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
+ long initialDelay, long period, TimeUnit unit) {
+ throw new UnsupportedOperationException();
+ }
+
+ public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
+ long initialDelay, long delay, TimeUnit unit) {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+ private static class MockScheduledExecutor
+ extends UnsupportedScheduledExecutor {
+ long executionDelay;
+ TimeUnit executionTimeUnit;
+
+ @Override
+ public ScheduledFuture<?> schedule(Runnable command, long delay,
+ TimeUnit unit) {
+ executionDelay = delay;
+ executionTimeUnit = unit;
+ return null;
+ }
+ }
+
+ @Test
+ public void testConstructor() {
+ new FormsAuthenticationHandler("username", "password",
+ new UnsupportedScheduledExecutor(),
+ new UnsupportedAuthenticationHandler());
+ }
+
+ @Test
+ public void testNullUserName() {
+ thrown.expect(NullPointerException.class);
+ new FormsAuthenticationHandler(null, "password",
+ new UnsupportedScheduledExecutor(),
+ new UnsupportedAuthenticationHandler());
+ }
+
+ @Test
+ public void testNullPassword() {
+ thrown.expect(NullPointerException.class);
+ new FormsAuthenticationHandler("username", null,
+ new UnsupportedScheduledExecutor(),
+ new UnsupportedAuthenticationHandler());
+ }
+
+ @Test
+ public void testNullScheduledExecutor() {
+ thrown.expect(NullPointerException.class);
+ new FormsAuthenticationHandler("username", "password", null,
+ new UnsupportedAuthenticationHandler());
+ }
+
+ @Test
+ public void testNullAuthenticationHandler() {
+ thrown.expect(NullPointerException.class);
+ new FormsAuthenticationHandler("username", "password",
+ new UnsupportedScheduledExecutor(),null);
+ }
+
+ @Test
+ public void testWindowsAuthentication() throws IOException {
+ FormsAuthenticationHandler formsHandler = new FormsAuthenticationHandler(
+ "username", "password", new UnsupportedScheduledExecutor(),
+ new MockAuthenticationHandler(false, null));
+ formsHandler.start();
+ assertFalse(formsHandler.isFormsAuthentication());
+ assertTrue(formsHandler.getAuthenticationCookies().isEmpty());
+ }
+
+ @Test
+ public void testEmptyUsernamePassword() throws IOException {
+ FormsAuthenticationHandler formsHandler = new FormsAuthenticationHandler(
+ "", "", new UnsupportedScheduledExecutor(),
+ new UnsupportedAuthenticationHandler());
+ formsHandler.start();
+ assertFalse(formsHandler.isFormsAuthentication());
+ assertTrue(formsHandler.getAuthenticationCookies().isEmpty());
+ }
+
+ @Test
+ public void testFormsAuthenticationNoError() throws IOException {
+ MockScheduledExecutor executor = new MockScheduledExecutor();
+ FormsAuthenticationHandler formsHandler = new FormsAuthenticationHandler(
+ "username", "password", executor, new MockAuthenticationHandler(true,
+ new AuthenticationResult("AuthenCookie", 99, "NO_ERROR")));
+ formsHandler.start();
+ assertTrue(formsHandler.isFormsAuthentication());
+ assertEquals(Collections.unmodifiableList(Arrays.asList("AuthenCookie")),
+ formsHandler.getAuthenticationCookies());
+ assertEquals(50, executor.executionDelay);
+ assertEquals(TimeUnit.SECONDS, executor.executionTimeUnit);
+ executor.shutdown();
+ }
+
+ @Test
+ public void testFormsAuthenticationPasswordMismatch() throws IOException {
+ FormsAuthenticationHandler formsHandler = new FormsAuthenticationHandler(
+ "username", "password", new UnsupportedScheduledExecutor(),
+ new MockAuthenticationHandler(true,
+ new AuthenticationResult(null, 99, "PASSWORD_NOT_MATCH")));
+ formsHandler.start();
+ assertTrue(formsHandler.isFormsAuthentication());
+ assertTrue(formsHandler.getAuthenticationCookies().isEmpty());
+ }
+}
diff --git a/test/com/google/enterprise/adaptor/sharepoint/SharePointFormsAuthenticationHandlerTest.java b/test/com/google/enterprise/adaptor/sharepoint/SharePointFormsAuthenticationHandlerTest.java
new file mode 100644
index 0000000..fb9251f
--- /dev/null
+++ b/test/com/google/enterprise/adaptor/sharepoint/SharePointFormsAuthenticationHandlerTest.java
@@ -0,0 +1,191 @@
+// Copyright 2014 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.sharepoint;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import com.microsoft.schemas.sharepoint.soap.authentication.AuthenticationMode;
+import com.microsoft.schemas.sharepoint.soap.authentication.AuthenticationSoap;
+import com.microsoft.schemas.sharepoint.soap.authentication.LoginErrorCode;
+import com.microsoft.schemas.sharepoint.soap.authentication.LoginResult;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.ws.Binding;
+import javax.xml.ws.BindingProvider;
+import javax.xml.ws.EndpointReference;
+import javax.xml.ws.handler.MessageContext;
+
+public class SharePointFormsAuthenticationHandlerTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ private static class UnsupportedAuthenticationSoap
+ implements AuthenticationSoap {
+
+ public LoginResult login(String username, String password) {
+ throw new UnsupportedOperationException();
+ }
+
+ public AuthenticationMode mode() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private static class MockFormsAuthenticationSoap
+ extends UnsupportedAuthenticationSoap implements BindingProvider {
+ @Override
+ public LoginResult login(String username, String password) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public AuthenticationMode mode() {
+ return AuthenticationMode.FORMS;
+ }
+
+ public Map<String, Object> getRequestContext() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Map<String, Object> getResponseContext() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Binding getBinding() {
+ throw new UnsupportedOperationException();
+ }
+
+ public EndpointReference getEndpointReference() {
+ throw new UnsupportedOperationException();
+ }
+
+ public <T extends EndpointReference> T
+ getEndpointReference(Class<T> clazz) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ @Test
+ public void testConstructor() {
+ new SharePointFormsAuthenticationHandler (
+ new UnsupportedAuthenticationSoap(), "username", "password");
+ }
+
+ @Test
+ public void testNullUserName() {
+ thrown.expect(NullPointerException.class);
+ new SharePointFormsAuthenticationHandler (
+ new UnsupportedAuthenticationSoap(), null, "password");
+ }
+
+ @Test
+ public void testNullPassword() {
+ thrown.expect(NullPointerException.class);
+ new SharePointFormsAuthenticationHandler (
+ new UnsupportedAuthenticationSoap(), "username", null);
+ }
+
+ @Test
+ public void testNullAuthenticationClient() {
+ thrown.expect(NullPointerException.class);
+ new SharePointFormsAuthenticationHandler ( null, "username", "password");
+ }
+
+ @Test
+ public void testSharePointWithWindowsAuthentication() throws IOException{
+ SharePointFormsAuthenticationHandler authenHandler
+ = new SharePointFormsAuthenticationHandler(
+ new MockFormsAuthenticationSoap(){
+ @Override public AuthenticationMode mode()
+ {
+ return AuthenticationMode.WINDOWS;
+ }
+ }, "username", "password");
+
+ assertFalse(authenHandler.isFormsAuthentication());
+ AuthenticationResult ar = authenHandler.authenticate();
+ assertNotNull(ar);
+ assertNull(ar.getCookie());
+ assertEquals(LoginErrorCode.NOT_IN_FORMS_AUTHENTICATION_MODE.toString(),
+ ar.getErrorCode());
+ }
+
+ @Test
+ public void testSharePointWithFormsPasswordMismatch() throws IOException {
+ SharePointFormsAuthenticationHandler authenHandler
+ = new SharePointFormsAuthenticationHandler(
+ new MockFormsAuthenticationSoap(){
+ @Override public LoginResult login(
+ String username, String password) {
+ LoginResult lr = new LoginResult();
+ lr.setErrorCode(LoginErrorCode.PASSWORD_NOT_MATCH);
+ return lr;
+ }
+ }, "username", "password");
+
+ assertTrue(authenHandler.isFormsAuthentication());
+ AuthenticationResult ar = authenHandler.authenticate();
+ assertNotNull(ar);
+ assertNull(ar.getCookie());
+ assertEquals(LoginErrorCode.PASSWORD_NOT_MATCH.toString(),
+ ar.getErrorCode());
+ }
+
+ @Test
+ public void testSharePointWithFormsAuthentication() throws IOException {
+ SharePointFormsAuthenticationHandler authenHandler
+ = new SharePointFormsAuthenticationHandler(
+ new MockFormsAuthenticationSoap() {
+ @Override public LoginResult login(
+ String username, String password) {
+ LoginResult lr = new LoginResult();
+ lr.setErrorCode(LoginErrorCode.NO_ERROR);
+ return lr;
+ }
+
+ @Override public Map<String, Object> getResponseContext() {
+ Map<String, Object> responseContext
+ = new HashMap<String, Object>();
+ Map<String, List<String>> responseHeaders
+ = new HashMap<String, List<String>>();
+ responseHeaders.put("Set-cookie",
+ Arrays.asList("AuthenticationCookie"));
+ responseContext.put(MessageContext.HTTP_RESPONSE_HEADERS,
+ Collections.unmodifiableMap(responseHeaders));
+ return Collections.unmodifiableMap(responseContext);
+ }
+ }, "username", "password");
+ assertTrue(authenHandler.isFormsAuthentication());
+ AuthenticationResult ar = authenHandler.authenticate();
+ assertNotNull(ar);
+ assertEquals("AuthenticationCookie", ar.getCookie());
+ assertEquals(LoginErrorCode.NO_ERROR.toString(),
+ ar.getErrorCode());
+ }
+}