Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 /* | |
ejona
2013/08/09 21:35:47
We need the copyright header. Remove this comment.
| |
2 * To change this template, choose Tools | Templates | |
3 * and open the template in the editor. | |
4 */ | |
5 package com.google.enterprise.adaptor.sharepoint; | |
6 | |
7 import com.google.common.annotations.VisibleForTesting; | |
8 import com.microsoft.schemas.sharepoint.soap.Authentication.AuthenticationMode; | |
9 import com.microsoft.schemas.sharepoint.soap.Authentication.AuthenticationSoap; | |
10 import com.microsoft.schemas.sharepoint.soap.Authentication.LoginErrorCode; | |
11 import com.microsoft.schemas.sharepoint.soap.Authentication.LoginResult; | |
12 import java.io.IOException; | |
ejona
2013/08/09 21:35:47
Newline between com. and java. sections.
| |
13 import java.net.Authenticator; | |
14 import java.net.PasswordAuthentication; | |
15 import java.net.URL; | |
16 import java.util.List; | |
17 import java.util.Map; | |
18 import java.util.concurrent.CopyOnWriteArrayList; | |
19 import java.util.concurrent.ScheduledExecutorService; | |
20 import java.util.concurrent.ScheduledThreadPoolExecutor; | |
21 import java.util.concurrent.TimeUnit; | |
22 import java.util.logging.Level; | |
23 import java.util.logging.Logger; | |
24 import javax.xml.namespace.QName; | |
ejona
2013/08/09 21:35:47
Newline between java. and javax. sections.
| |
25 import javax.xml.ws.BindingProvider; | |
26 import javax.xml.ws.EndpointReference; | |
27 import javax.xml.ws.Service; | |
28 import javax.xml.ws.handler.MessageContext; | |
29 import javax.xml.ws.wsaddressing.W3CEndpointReferenceBuilder; | |
30 | |
31 /** | |
32 * | |
ejona
2013/08/09 21:35:47
Let's have a description here.
| |
33 * @author tvartak | |
34 */ | |
35 | |
36 @VisibleForTesting | |
37 interface AuthenticationHandler {· | |
ejona
2013/08/09 21:35:47
Only one top-level class/interface per file. This
| |
38 public List<String> getAuthenticationCookies(); | |
39 } | |
40 public class SharePointAuthenticationHandler implements AuthenticationHandler { | |
ejona
2013/08/09 21:35:47
I'd prefer something more like AuthenticationHandl
ejona
2013/08/09 21:35:47
No need for public visibility. Make it package-pri
| |
41 /** SharePoint's namespace. */ | |
42 private static final String XMLNS | |
43 = "http://schemas.microsoft.com/sharepoint/soap/"; | |
44 ·· | |
45 private static final Logger log | |
46 = Logger.getLogger(SharePointAuthenticationHandler.class.getName()); | |
47 // Default time out for forms authentication with .NET is 30 mins | |
48 // using 20 mins as refresh duration | |
49 private static final long DEFAULT_COOKIE_TIMEOUT = 1200; | |
ejona
2013/08/09 21:35:47
Add a unit. DEFAULT_COOKIE_TIMEOUT_SECS or SECONDS
ejona
2013/08/09 21:35:47
Make this 1800, since 30 minutes is the "default c
| |
50 ·· | |
51 private final AuthenticationFactory authenticationFactory; | |
52 private final String virtualServer; | |
53 private final String userName; | |
54 private final String password; | |
55 private final int port; | |
56 private final ScheduledExecutorService executor; | |
ejona
2013/08/09 21:35:47
Fix indent.
| |
57 private final Runnable refreshRunnable = new RefreshRunnable(); | |
58 private String authenticationCookies; | |
59 private List<String> authenticationCookiesList· | |
ejona
2013/08/09 21:35:47
We should add final to this.
| |
60 = new CopyOnWriteArrayList<String>(); | |
61 private AuthenticationMode authenticationMode; | |
62 private final AuthenticationSoap authenticationClient; | |
63 ·· | |
64 @VisibleForTesting···· | |
65 SharePointAuthenticationHandler(String virtualServer, int port, | |
ejona
2013/08/09 21:35:47
port is unused.
| |
66 String userName, String password, ScheduledExecutorService executor, | |
67 AuthenticationFactory authenticationFactory) { | |
ejona
2013/08/09 21:35:47
Pass in the actual AuthenticationSoap instead of t
| |
68 this.virtualServer = virtualServer; | |
69 this.userName = userName; | |
70 this.password = password;·· | |
71 this.authenticationFactory = authenticationFactory; | |
72 this.port = port; | |
73 this.executor = executor; | |
74 authenticationClient | |
75 = authenticationFactory.newAuthentication( | |
76 virtualServer + "/_vti_bin/Authentication.asmx"); | |
77 } | |
78 ·· | |
79 @Override | |
80 public List<String> getAuthenticationCookies() { | |
81 return authenticationCookiesList; | |
ejona
2013/08/09 21:35:47
Wrap with Collections.unmodifiableList.
| |
82 } | |
83 ·· | |
84 private void performAuthentication() throws IOException { | |
ejona
2013/08/09 21:35:47
Do you think refreshCookies would be more a approp
| |
85 log.log(Level.FINE, "AuthenticationMode = {0}", authenticationMode); | |
86 if (authenticationMode == AuthenticationMode.FORMS) { | |
ejona
2013/08/09 21:35:47
Invert condition to reduce indentation?
if (authe
| |
87 LoginResult result = null; | |
88 try { | |
89 result = authenticationClient.login(userName, password); | |
ejona
2013/08/09 21:35:47
Fix indent.
| |
90 } catch (Exception ex) { | |
ejona
2013/08/09 21:35:47
Can we be more precise than Exception?
| |
91 log.log(Level.WARNING, | |
92 "Possible SP2013 environment with windows authentication", ex); | |
Tanmay Vartak
2013/08/08 23:17:35
here we can actually look for "Site is not configu
| |
93 return; | |
94 } | |
95 log.log(Level.FINE, "Login Result = {0}", result.getErrorCode()); | |
96 log.log(Level.FINE,· | |
97 "Login Cookie Expiration in = {0}", result.getTimeoutSeconds()); | |
98 if (result.getErrorCode() != LoginErrorCode.NO_ERROR) { | |
99 throw new IOException("Could not login"); | |
ejona
2013/08/09 21:35:47
Include error code and more context, like somethin
| |
100 } | |
101 Map<String, Object> responseHeaders | |
102 = (Map<String, Object>) ((BindingProvider) authenticationClient) | |
103 .getResponseContext().get(MessageContext.HTTP_RESPONSE_HEADERS); | |
104 log.log(Level.FINE, "Response headers: {0}", responseHeaders);······ | |
105 if (authenticationCookiesList.isEmpty()) { | |
106 authenticationCookiesList.add( | |
107 ((List<String>) responseHeaders.get("Set-cookie")).get(0)); | |
ejona
2013/08/09 21:35:47
Get the cookie String before the two cases?
| |
108 } else { | |
109 authenticationCookiesList.set(0, | |
ejona
2013/08/09 21:35:47
Fix indentation.
| |
110 ((List<String>) responseHeaders.get("Set-cookie")).get(0)); | |
111 }······ | |
112 long rerunAfter = (result.getTimeoutSeconds() == null) ?· | |
ejona
2013/08/09 21:35:47
Handle the getTimeoutSeconds() == null separately
| |
113 DEFAULT_COOKIE_TIMEOUT : (result.getTimeoutSeconds() + 1)/2; | |
ejona
2013/08/09 21:35:47
Spaces on either side of /.
| |
114 executor.schedule(refreshRunnable, rerunAfter, TimeUnit.SECONDS); | |
115 log.log(Level.FINE, | |
116 "Authentication Cookie is {0}", authenticationCookiesList); | |
117 } | |
118 } | |
119 · | |
120 public void start() throws IOException { | |
121 authenticationMode = authenticationClient.mode(); | |
122 performAuthentication(); | |
123 } | |
124 ·· | |
125 @VisibleForTesting | |
126 interface AuthenticationFactory { | |
127 public AuthenticationSoap newAuthentication(String endpoint); | |
128 } | |
129 ·· | |
130 static class AuthenticationFactoryImpl implements AuthenticationFactory { | |
131 private final Service authenticationService; | |
132 ···· | |
133 public AuthenticationFactoryImpl() { | |
134 URL url = AuthenticationSoap.class.getResource("Authentication.wsdl"); | |
135 QName qname = new QName(XMLNS, "Authentication"); | |
136 this.authenticationService = Service.create(url, qname); | |
137 } | |
138 ···· | |
139 @Override | |
140 public AuthenticationSoap newAuthentication(String endpoint) { | |
141 EndpointReference endpointRef = new W3CEndpointReferenceBuilder() | |
142 .address(endpoint).build(); | |
143 return· | |
144 authenticationService.getPort(endpointRef, AuthenticationSoap.class); | |
145 } | |
146 } | |
147 ·· | |
148 private class RefreshRunnable implements Runnable { | |
149 @Override | |
150 public void run() { | |
151 try { | |
152 performAuthentication(); | |
153 } catch(Exception ex) { | |
154 log.log(Level.WARNING, "Error performing forms authentication!!", ex);·············· | |
ejona
2013/08/09 21:35:47
No exclamation marks? We don't tend to put them, I
| |
155 executor.schedule(this, 5, TimeUnit.MINUTES); | |
156 } | |
157 } | |
158 } | |
159 } | |
OLD | NEW |