/* $Id$ */ /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.manifoldcf.authorities.authorities.sharepoint; import org.apache.manifoldcf.core.interfaces.*; import org.apache.manifoldcf.agents.interfaces.*; import org.apache.manifoldcf.authorities.interfaces.*; import org.apache.manifoldcf.authorities.system.Logging; import org.apache.manifoldcf.authorities.system.ManifoldCF; import org.apache.manifoldcf.core.util.URLEncoder; import org.apache.manifoldcf.core.util.URLDecoder; import org.apache.manifoldcf.connectorcommon.interfaces.*; import java.io.*; import java.util.*; import java.net.*; import java.util.concurrent.TimeUnit; import javax.naming.*; import javax.naming.ldap.*; import javax.naming.directory.*; import org.apache.http.conn.HttpClientConnectionManager; import org.apache.http.client.HttpClient; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.protocol.HttpRequestExecutor; import org.apache.http.impl.client.HttpClients; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.CredentialsProvider; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.config.SocketConfig; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.DefaultHostnameVerifier; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.auth.AuthScope; import org.apache.http.auth.NTCredentials; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultRedirectStrategy; import org.apache.http.util.EntityUtils; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.protocol.HttpContext; import org.apache.http.HttpHost; /** This is the native SharePoint implementation of the IAuthorityConnector interface. */ public class SharePointAuthority extends org.apache.manifoldcf.authorities.authorities.BaseAuthorityConnector { public static final String _rcsid = "@(#)$Id$"; // Data from the parameters /** Cache manager. */ private ICacheManager cacheManager = null; private boolean hasSessionParameters = false; /** Length of time that a SharePoint session can remain idle */ private static final long SharePointExpirationInterval = 300000L; // SharePoint server parameters // These are needed for caching, so they are set at connect() time private boolean isClaimSpace = false; private String serverProtocol = null; private String serverUrl = null; private String fileBaseUrl = null; private String serverUserName = null; private String password = null; private String ntlmDomain = null; private String serverName = null; private String serverPortString = null; private String serverLocation = null; private String strippedUserName = null; private String encodedServerLocation = null; private String keystoreData = null; private String proxyHost = null; private String proxyPortString = null; private String proxyUsername = null; private String proxyPassword = null; private String proxyDomain = null; private String cacheLRUsize = null; private String cacheLifetime = null; // These are calculated when the session is set up private int serverPort = -1; private SPSProxyHelper proxy = null; private long sharepointSessionTimeout; private long responseLifetime = -1L; private int LRUsize = -1; private IKeystoreManager keystoreManager = null; private HttpClientConnectionManager connectionManager = null; private HttpClient httpClient = null; // Current host name private static String currentHost = null; static { // Find the current host name try { java.net.InetAddress addr = java.net.InetAddress.getLocalHost(); // Get hostname currentHost = addr.getHostName(); } catch (UnknownHostException e) { } } /** Constructor. */ public SharePointAuthority() { } /** Set thread context. */ @Override public void setThreadContext(IThreadContext tc) throws ManifoldCFException { super.setThreadContext(tc); cacheManager = CacheManagerFactory.make(tc); } /** Clear thread context. */ @Override public void clearThreadContext() { super.clearThreadContext(); cacheManager = null; } /** Connect. The configuration parameters are included. *@param configParams are the configuration parameters for this connection. */ @Override public void connect(ConfigParams configParams) { super.connect(configParams); // Pick up all the parameters that go into the cache key here cacheLifetime = configParams.getParameter(SharePointConfig.PARAM_CACHELIFETIME); if (cacheLifetime == null) cacheLifetime = "1"; cacheLRUsize = configParams.getParameter(SharePointConfig.PARAM_CACHELRUSIZE); if (cacheLRUsize == null) cacheLRUsize = "1000"; String serverVersion = configParams.getParameter( SharePointConfig.PARAM_SERVERVERSION ); if (serverVersion == null) serverVersion = "4.0"; // Authority needs to do nothing with SharePoint version right now. String serverClaimSpace = configParams.getParameter( SharePointConfig.PARAM_SERVERCLAIMSPACE); if (serverClaimSpace == null) serverClaimSpace = "false"; isClaimSpace = serverClaimSpace.equals("true"); serverProtocol = configParams.getParameter( SharePointConfig.PARAM_SERVERPROTOCOL ); if (serverProtocol == null) serverProtocol = "http"; serverName = configParams.getParameter( SharePointConfig.PARAM_SERVERNAME ); serverPortString = configParams.getParameter( SharePointConfig.PARAM_SERVERPORT ); serverLocation = configParams.getParameter(SharePointConfig.PARAM_SERVERLOCATION); if (serverLocation == null) serverLocation = ""; if (serverLocation.endsWith("/")) serverLocation = serverLocation.substring(0,serverLocation.length()-1); if (serverLocation.length() > 0 && !serverLocation.startsWith("/")) serverLocation = "/" + serverLocation; encodedServerLocation = serverLocation; serverLocation = decodePath(serverLocation); serverUserName = configParams.getParameter(SharePointConfig.PARAM_SERVERUSERNAME); password = configParams.getObfuscatedParameter(SharePointConfig.PARAM_SERVERPASSWORD); int index = serverUserName.indexOf("\\"); if (index != -1) { strippedUserName = serverUserName.substring(index+1); ntlmDomain = serverUserName.substring(0,index); } else { strippedUserName = null; ntlmDomain = null; } proxyHost = params.getParameter(SharePointConfig.PARAM_PROXYHOST); proxyPortString = params.getParameter(SharePointConfig.PARAM_PROXYPORT); proxyUsername = params.getParameter(SharePointConfig.PARAM_PROXYUSER); proxyPassword = params.getObfuscatedParameter(SharePointConfig.PARAM_PROXYPASSWORD); proxyDomain = params.getParameter(SharePointConfig.PARAM_PROXYDOMAIN); keystoreData = params.getParameter(SharePointConfig.PARAM_SERVERKEYSTORE); } // All methods below this line will ONLY be called if a connect() call succeeded // on this instance! /** Check connection for sanity. */ @Override public String check() throws ManifoldCFException { getSharePointSession(); try { URL urlServer = new URL( serverUrl ); } catch ( MalformedURLException e ) { return "Illegal SharePoint url: "+e.getMessage(); } try { proxy.checkConnection( "/" ); } catch (ManifoldCFException e) { return e.getMessage(); } return super.check(); } /** Poll. The connection should be closed if it has been idle for too long. */ @Override public void poll() throws ManifoldCFException { long currentTime = System.currentTimeMillis(); if (proxy != null && System.currentTimeMillis() >= sharepointSessionTimeout) expireSharePointSession(); if (connectionManager != null) connectionManager.closeIdleConnections(60000L,TimeUnit.MILLISECONDS); super.poll(); } /** This method is called to assess whether to count this connector instance should * actually be counted as being connected. *@return true if the connector instance is actually connected. */ @Override public boolean isConnected() { return connectionManager != null; } /** Close the connection. Call this before discarding the repository connector. */ @Override public void disconnect() throws ManifoldCFException { // Clean up caching parameters cacheLifetime = null; cacheLRUsize = null; // Clean up SharePoint parameters isClaimSpace = false; serverUrl = null; fileBaseUrl = null; serverUserName = null; strippedUserName = null; password = null; ntlmDomain = null; serverName = null; serverLocation = null; encodedServerLocation = null; serverPort = -1; proxyHost = null; proxyPortString = null; proxyUsername = null; proxyPassword = null; proxyDomain = null; keystoreData = null; keystoreManager = null; proxy = null; httpClient = null; if (connectionManager != null) connectionManager.shutdown(); connectionManager = null; hasSessionParameters = false; super.disconnect(); } /** Obtain the access tokens for a given user name. *@param userName is the user name or identifier. *@return the response tokens (according to the current authority). * (Should throws an exception only when a condition cannot be properly described within the authorization response object.) */ @Override public AuthorizationResponse getAuthorizationResponse(String userName) throws ManifoldCFException { getSessionParameters(); // Construct a cache description object ICacheDescription objectDescription = new AuthorizationResponseDescription(userName, serverName,serverPortString,serverLocation,serverProtocol,serverUserName,password, this.responseLifetime,this.LRUsize); // Enter the cache ICacheHandle ch = cacheManager.enterCache(new ICacheDescription[]{objectDescription},null,null); try { ICacheCreateHandle createHandle = cacheManager.enterCreateSection(ch); try { // Lookup the object AuthorizationResponse response = (AuthorizationResponse)cacheManager.lookupObject(createHandle,objectDescription); if (response != null) return response; // Create the object. response = getAuthorizationResponseUncached(userName); // Save it in the cache cacheManager.saveObject(createHandle,objectDescription,response); // And return it... return response; } finally { cacheManager.leaveCreateSection(createHandle); } } finally { cacheManager.leaveCache(ch); } } /** Obtain the access tokens for a given user name, uncached. *@param userName is the user name or identifier. *@return the response tokens (according to the current authority). * (Should throws an exception only when a condition cannot be properly described within the authorization response object.) */ protected AuthorizationResponse getAuthorizationResponseUncached(String userName) throws ManifoldCFException { //String searchBase = "CN=Administrator,CN=Users,DC=qa-ad-76,DC=metacarta,DC=com"; int index = userName.indexOf("@"); if (index == -1) throw new ManifoldCFException("Username is in unexpected form (no @): '"+userName+"'"); String userPart = userName.substring(0,index); String domainPart = userName.substring(index+1); // First, look up user in SharePoint. getSharePointSession(); List<String> sharePointTokens = proxy.getAccessTokens("/", domainPart + "\\" + userPart); if (sharePointTokens == null) return RESPONSE_USERNOTFOUND_ADDITIVE; return new AuthorizationResponse(sharePointTokens.toArray(new String[0]),AuthorizationResponse.RESPONSE_OK); } /** Obtain the default access tokens for a given user name. *@param userName is the user name or identifier. *@return the default response tokens, presuming that the connect method fails. */ @Override public AuthorizationResponse getDefaultAuthorizationResponse(String userName) { // The default response if the getConnection method fails return RESPONSE_UNREACHABLE_ADDITIVE; } // UI support methods. // // These support methods are involved in setting up authority connection configuration information. The configuration methods cannot assume that the // current authority object is connected. That is why they receive a thread context argument. /** Output the configuration header section. * This method is called in the head section of the connector's configuration page. Its purpose is to add the required tabs to the list, and to output any * javascript methods that might be needed by the configuration editing HTML. *@param threadContext is the local thread context. *@param out is the output to which any HTML should be sent. *@param parameters are the configuration parameters, as they currently exist, for this connection being configured. *@param tabsArray is an array of tab names. Add to this array any tab names that are specific to the connector. */ @Override public void outputConfigurationHeader(IThreadContext threadContext, IHTTPOutput out, Locale locale, ConfigParams parameters, List<String> tabsArray) throws ManifoldCFException, IOException { tabsArray.add(Messages.getString(locale,"SharePointAuthority.Server")); tabsArray.add(Messages.getString(locale,"SharePointAuthority.Cache")); Messages.outputResourceWithVelocity(out,locale,"editConfiguration.js",null); } /** Output the configuration body section. * This method is called in the body section of the authority connector's configuration page. Its purpose is to present the required form elements for editing. * The coder can presume that the HTML that is output from this configuration will be within appropriate <html>, <body>, and <form> tags. The name of the * form is "editconnection". *@param threadContext is the local thread context. *@param out is the output to which any HTML should be sent. *@param parameters are the configuration parameters, as they currently exist, for this connection being configured. *@param tabName is the current tab name. */ @Override public void outputConfigurationBody(IThreadContext threadContext, IHTTPOutput out, Locale locale, ConfigParams parameters, String tabName) throws ManifoldCFException, IOException { Map<String,Object> velocityContext = new HashMap<String,Object>(); velocityContext.put("TabName",tabName); fillInCacheTab(velocityContext,out,parameters); fillInServerTab(velocityContext,out,parameters); Messages.outputResourceWithVelocity(out,locale,"editConfiguration_Cache.html",velocityContext); Messages.outputResourceWithVelocity(out,locale,"editConfiguration_Server.html",velocityContext); } protected static void fillInServerTab(Map<String,Object> velocityContext, IHTTPOutput out, ConfigParams parameters) throws ManifoldCFException { String serverVersion = parameters.getParameter(SharePointConfig.PARAM_SERVERVERSION); if (serverVersion == null) serverVersion = "2.0"; String serverClaimSpace = parameters.getParameter(SharePointConfig.PARAM_SERVERCLAIMSPACE); if (serverClaimSpace == null) serverClaimSpace = "false"; String serverProtocol = parameters.getParameter(SharePointConfig.PARAM_SERVERPROTOCOL); if (serverProtocol == null) serverProtocol = "http"; String serverName = parameters.getParameter(SharePointConfig.PARAM_SERVERNAME); if (serverName == null) serverName = "localhost"; String serverPort = parameters.getParameter(SharePointConfig.PARAM_SERVERPORT); if (serverPort == null) serverPort = ""; String serverLocation = parameters.getParameter(SharePointConfig.PARAM_SERVERLOCATION); if (serverLocation == null) serverLocation = ""; String userName = parameters.getParameter(SharePointConfig.PARAM_SERVERUSERNAME); if (userName == null) userName = ""; String password = parameters.getObfuscatedParameter(SharePointConfig.PARAM_SERVERPASSWORD); if (password == null) password = ""; else password = out.mapPasswordToKey(password); String keystore = parameters.getParameter(SharePointConfig.PARAM_SERVERKEYSTORE); IKeystoreManager localKeystore; if (keystore == null) localKeystore = KeystoreManagerFactory.make(""); else localKeystore = KeystoreManagerFactory.make("",keystore); List<Map<String,String>> certificates = new ArrayList<Map<String,String>>(); String[] contents = localKeystore.getContents(); for (String alias : contents) { String description = localKeystore.getDescription(alias); if (description.length() > 128) description = description.substring(0,125) + "..."; Map<String,String> certificate = new HashMap<String,String>(); certificate.put("ALIAS", alias); certificate.put("DESCRIPTION", description); certificates.add(certificate); } String proxyHost = parameters.getParameter(SharePointConfig.PARAM_PROXYHOST); if (proxyHost == null) proxyHost = ""; String proxyPort = parameters.getParameter(SharePointConfig.PARAM_PROXYPORT); if (proxyPort == null) proxyPort = ""; String proxyUser = parameters.getParameter(SharePointConfig.PARAM_PROXYUSER); if (proxyUser == null) proxyUser = ""; String proxyPassword = parameters.getObfuscatedParameter(SharePointConfig.PARAM_PROXYPASSWORD); if (proxyPassword == null) proxyPassword = ""; else proxyPassword = out.mapPasswordToKey(proxyPassword); String proxyDomain = parameters.getParameter(SharePointConfig.PARAM_PROXYDOMAIN); if (proxyDomain == null) proxyDomain = ""; // Fill in context velocityContext.put("SERVERVERSION", serverVersion); velocityContext.put("SERVERCLAIMSPACE", serverClaimSpace); velocityContext.put("SERVERPROTOCOL", serverProtocol); velocityContext.put("SERVERNAME", serverName); velocityContext.put("SERVERPORT", serverPort); velocityContext.put("SERVERLOCATION", serverLocation); velocityContext.put("SERVERUSERNAME", userName); velocityContext.put("SERVERPASSWORD", password); if (keystore != null) velocityContext.put("KEYSTORE", keystore); velocityContext.put("CERTIFICATELIST", certificates); velocityContext.put("PROXYHOST", proxyHost); velocityContext.put("PROXYPORT", proxyPort); velocityContext.put("PROXYUSER", proxyUser); velocityContext.put("PROXYPASSWORD", proxyPassword); velocityContext.put("PROXYDOMAIN", proxyDomain); } protected static void fillInCacheTab(Map<String,Object> velocityContext, IPasswordMapperActivity mapper, ConfigParams parameters) { String cacheLifetime = parameters.getParameter(SharePointConfig.PARAM_CACHELIFETIME); if (cacheLifetime == null) cacheLifetime = "1"; velocityContext.put("CACHELIFETIME",cacheLifetime); String cacheLRUsize = parameters.getParameter(SharePointConfig.PARAM_CACHELRUSIZE); if (cacheLRUsize == null) cacheLRUsize = "1000"; velocityContext.put("CACHELRUSIZE",cacheLRUsize); } /** Process a configuration post. * This method is called at the start of the authority connector's configuration page, whenever there is a possibility that form data for a connection has been * posted. Its purpose is to gather form information and modify the configuration parameters accordingly. * The name of the posted form is "editconnection". *@param threadContext is the local thread context. *@param variableContext is the set of variables available from the post, including binary file post information. *@param parameters are the configuration parameters, as they currently exist, for this connection being configured. *@return null if all is well, or a string error message if there is an error that should prevent saving of the connection (and cause a redirection to an error page). */ @Override public String processConfigurationPost(IThreadContext threadContext, IPostParameters variableContext, Locale locale, ConfigParams parameters) throws ManifoldCFException { // Cache parameters String cacheLifetime = variableContext.getParameter("cachelifetime"); if (cacheLifetime != null) parameters.setParameter(SharePointConfig.PARAM_CACHELIFETIME,cacheLifetime); String cacheLRUsize = variableContext.getParameter("cachelrusize"); if (cacheLRUsize != null) parameters.setParameter(SharePointConfig.PARAM_CACHELRUSIZE,cacheLRUsize); // SharePoint server parameters String serverVersion = variableContext.getParameter("serverVersion"); if (serverVersion != null) parameters.setParameter(SharePointConfig.PARAM_SERVERVERSION,serverVersion); String serverClaimSpace = variableContext.getParameter("serverClaimSpace"); if (serverClaimSpace != null) parameters.setParameter(SharePointConfig.PARAM_SERVERCLAIMSPACE,serverClaimSpace); String serverProtocol = variableContext.getParameter("serverProtocol"); if (serverProtocol != null) parameters.setParameter(SharePointConfig.PARAM_SERVERPROTOCOL,serverProtocol); String serverName = variableContext.getParameter("serverName"); if (serverName != null) parameters.setParameter(SharePointConfig.PARAM_SERVERNAME,serverName); String serverPort = variableContext.getParameter("serverPort"); if (serverPort != null) parameters.setParameter(SharePointConfig.PARAM_SERVERPORT,serverPort); String serverLocation = variableContext.getParameter("serverLocation"); if (serverLocation != null) parameters.setParameter(SharePointConfig.PARAM_SERVERLOCATION,serverLocation); String userName = variableContext.getParameter("serverUserName"); if (userName != null) parameters.setParameter(SharePointConfig.PARAM_SERVERUSERNAME,userName); String password = variableContext.getParameter("serverPassword"); if (password != null) parameters.setObfuscatedParameter(SharePointConfig.PARAM_SERVERPASSWORD,variableContext.mapKeyToPassword(password)); String proxyHost = variableContext.getParameter("proxyhost"); if (proxyHost != null) parameters.setParameter(SharePointConfig.PARAM_PROXYHOST,proxyHost); String proxyPort = variableContext.getParameter("proxyport"); if (proxyPort != null) parameters.setParameter(SharePointConfig.PARAM_PROXYPORT,proxyPort); String proxyUser = variableContext.getParameter("proxyuser"); if (proxyUser != null) parameters.setParameter(SharePointConfig.PARAM_PROXYUSER,proxyUser); String proxyPassword = variableContext.getParameter("proxypassword"); if (proxyPassword != null) parameters.setObfuscatedParameter(SharePointConfig.PARAM_PROXYPASSWORD,variableContext.mapKeyToPassword(proxyPassword)); String proxyDomain = variableContext.getParameter("proxydomain"); if (proxyDomain != null) parameters.setParameter(SharePointConfig.PARAM_PROXYDOMAIN,proxyDomain); String keystoreValue = variableContext.getParameter("keystoredata"); if (keystoreValue != null) parameters.setParameter(SharePointConfig.PARAM_SERVERKEYSTORE,keystoreValue); String configOp = variableContext.getParameter("configop"); if (configOp != null) { if (configOp.equals("Delete")) { String alias = variableContext.getParameter("shpkeystorealias"); keystoreValue = parameters.getParameter(SharePointConfig.PARAM_SERVERKEYSTORE); IKeystoreManager mgr; if (keystoreValue != null) mgr = KeystoreManagerFactory.make("",keystoreValue); else mgr = KeystoreManagerFactory.make(""); mgr.remove(alias); parameters.setParameter(SharePointConfig.PARAM_SERVERKEYSTORE,mgr.getString()); } else if (configOp.equals("Add")) { String alias = IDFactory.make(threadContext); byte[] certificateValue = variableContext.getBinaryBytes("shpcertificate"); keystoreValue = parameters.getParameter(SharePointConfig.PARAM_SERVERKEYSTORE); IKeystoreManager mgr; if (keystoreValue != null) mgr = KeystoreManagerFactory.make("",keystoreValue); else mgr = KeystoreManagerFactory.make(""); java.io.InputStream is = new java.io.ByteArrayInputStream(certificateValue); String certError = null; try { mgr.importCertificate(alias,is); } catch (Throwable e) { certError = e.getMessage(); } finally { try { is.close(); } catch (IOException e) { // Don't report anything } } if (certError != null) { // Redirect to error page return "Illegal certificate: "+certError; } parameters.setParameter(SharePointConfig.PARAM_SERVERKEYSTORE,mgr.getString()); } } return null; } /** View configuration. * This method is called in the body section of the authority connector's view configuration page. Its purpose is to present the connection information to the user. * The coder can presume that the HTML that is output from this configuration will be within appropriate <html> and <body> tags. *@param threadContext is the local thread context. *@param out is the output to which any HTML should be sent. *@param parameters are the configuration parameters, as they currently exist, for this connection being configured. */ @Override public void viewConfiguration(IThreadContext threadContext, IHTTPOutput out, Locale locale, ConfigParams parameters) throws ManifoldCFException, IOException { Map<String,Object> velocityContext = new HashMap<String,Object>(); fillInCacheTab(velocityContext,out,parameters); fillInServerTab(velocityContext,out,parameters); Messages.outputResourceWithVelocity(out,locale,"viewConfiguration.html",velocityContext); } // Protected methods /** Get parameters needed for caching. */ protected void getSessionParameters() throws ManifoldCFException { if (!hasSessionParameters) { try { responseLifetime = Long.parseLong(this.cacheLifetime) * 60L * 1000L; LRUsize = Integer.parseInt(this.cacheLRUsize); } catch (NumberFormatException e) { throw new ManifoldCFException("Cache lifetime or Cache LRU size must be an integer: "+e.getMessage(),e); } hasSessionParameters = true; } } protected void getSharePointSession() throws ManifoldCFException { if (proxy == null) { // Set up server URL try { if (serverPortString == null || serverPortString.length() == 0) { if (serverProtocol.equals("https")) this.serverPort = 443; else this.serverPort = 80; } else this.serverPort = Integer.parseInt(serverPortString); } catch (NumberFormatException e) { throw new ManifoldCFException(e.getMessage(),e); } int proxyPort = 8080; if (proxyPortString != null && proxyPortString.length() > 0) { try { proxyPort = Integer.parseInt(proxyPortString); } catch (NumberFormatException e) { throw new ManifoldCFException(e.getMessage(),e); } } serverUrl = serverProtocol + "://" + serverName; if (serverProtocol.equals("https")) { if (serverPort != 443) serverUrl += ":" + Integer.toString(serverPort); } else { if (serverPort != 80) serverUrl += ":" + Integer.toString(serverPort); } fileBaseUrl = serverUrl + encodedServerLocation; int connectionTimeout = 60000; int socketTimeout = 900000; // Set up ssl if indicated SSLConnectionSocketFactory myFactory = null; if (keystoreData != null) { keystoreManager = KeystoreManagerFactory.make("",keystoreData); myFactory = new SSLConnectionSocketFactory(keystoreManager.getSecureSocketFactory(), new DefaultHostnameVerifier()); } else { myFactory = SSLConnectionSocketFactory.getSocketFactory(); } PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager(RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", myFactory) .build()); poolingConnectionManager.setDefaultMaxPerRoute(1); poolingConnectionManager.setValidateAfterInactivity(2000); poolingConnectionManager.setDefaultSocketConfig(SocketConfig.custom() .setTcpNoDelay(true) .setSoTimeout(socketTimeout) .build()); connectionManager = poolingConnectionManager; CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); if (strippedUserName != null) { credentialsProvider.setCredentials( new AuthScope(serverName,serverPort), new NTCredentials(strippedUserName, password, currentHost, ntlmDomain)); } RequestConfig.Builder requestBuilder = RequestConfig.custom() .setCircularRedirectsAllowed(true) .setSocketTimeout(socketTimeout) .setExpectContinueEnabled(false) .setConnectTimeout(connectionTimeout) .setConnectionRequestTimeout(socketTimeout); // If there's a proxy, set that too. if (proxyHost != null && proxyHost.length() > 0) { // Configure proxy authentication if (proxyUsername != null && proxyUsername.length() > 0) { if (proxyPassword == null) proxyPassword = ""; if (proxyDomain == null) proxyDomain = ""; credentialsProvider.setCredentials( new AuthScope(proxyHost, proxyPort), new NTCredentials(proxyUsername, proxyPassword, currentHost, proxyDomain)); } HttpHost proxy = new HttpHost(proxyHost, proxyPort); requestBuilder.setProxy(proxy); } HttpClientBuilder builder = HttpClients.custom() .setConnectionManager(connectionManager) .disableAutomaticRetries() .setDefaultRequestConfig(requestBuilder.build()) .setDefaultCredentialsProvider(credentialsProvider); builder.setRequestExecutor(new HttpRequestExecutor(socketTimeout)) .setRedirectStrategy(new DefaultRedirectStrategy()); httpClient = builder.build(); proxy = new SPSProxyHelper( serverUrl, encodedServerLocation, serverLocation, serverUserName, password, org.apache.manifoldcf.connectorcommon.common.CommonsHTTPSender.class, "client-config.wsdd", httpClient, isClaimSpace ); } sharepointSessionTimeout = System.currentTimeMillis() + SharePointExpirationInterval; } protected void expireSharePointSession() throws ManifoldCFException { serverPort = -1; serverUrl = null; fileBaseUrl = null; keystoreManager = null; proxy = null; httpClient = null; if (connectionManager != null) connectionManager.shutdown(); connectionManager = null; } /** Decode a path item. */ public static String pathItemDecode(String pathItem) { return URLDecoder.decode(pathItem.replaceAll("\\%20","+")); } /** Encode a path item. */ public static String pathItemEncode(String pathItem) { String output = URLEncoder.encode(pathItem); return output.replaceAll("\\+","%20"); } /** Given a path that is /-separated, and otherwise encoded, decode properly to convert to * unencoded form. */ public static String decodePath(String relPath) { StringBuilder sb = new StringBuilder(); String[] pathEntries = relPath.split("/"); int k = 0; boolean isFirst = true; while (k < pathEntries.length) { if (isFirst) isFirst = false; else sb.append("/"); sb.append(pathItemDecode(pathEntries[k++])); } return sb.toString(); } /** Given a path that is /-separated, and otherwise unencoded, encode properly for an actual * URI */ public static String encodePath(String relPath) { StringBuilder sb = new StringBuilder(); String[] pathEntries = relPath.split("/"); int k = 0; boolean isFirst = true; while (k < pathEntries.length) { if (isFirst) isFirst = false; else sb.append("/"); sb.append(pathItemEncode(pathEntries[k++])); } return sb.toString(); } protected static StringSet emptyStringSet = new StringSet(); /** This is the cache object descriptor for cached access tokens from * this connector. */ protected static class AuthorizationResponseDescription extends org.apache.manifoldcf.core.cachemanager.BaseDescription { /** The user name */ protected final String userName; /** The response lifetime */ protected final long responseLifetime; /** The expiration time */ protected long expirationTime = -1; // Parameters designed to guarantee cache key uniqueness protected final String serverName; protected final String serverPortString; protected final String serverLocation; protected final String serverProtocol; protected final String serverUserName; protected final String password; /** Constructor. */ public AuthorizationResponseDescription(String userName, String serverName, String serverPortString, String serverLocation, String serverProtocol, String serverUserName, String password, long responseLifetime, int LRUsize) { super("SharePointAuthority",LRUsize); this.userName = userName; this.responseLifetime = responseLifetime; this.serverName = serverName; this.serverPortString = serverPortString; this.serverLocation = serverLocation; this.serverProtocol = serverProtocol; this.serverUserName = serverUserName; this.password = password; } /** Return the invalidation keys for this object. */ public StringSet getObjectKeys() { return emptyStringSet; } /** Get the critical section name, used for synchronizing the creation of the object */ public String getCriticalSectionName() { StringBuilder sb = new StringBuilder(getClass().getName()); sb.append("-").append(userName); sb.append("-").append(serverName); sb.append("-").append(serverPortString); sb.append("-").append(serverLocation); sb.append("-").append(serverProtocol); sb.append("-").append(serverUserName); sb.append("-").append(password); return sb.toString(); } /** Return the object expiration interval */ public long getObjectExpirationTime(long currentTime) { if (expirationTime == -1) expirationTime = currentTime + responseLifetime; return expirationTime; } public int hashCode() { int rval = userName.hashCode(); rval += serverName.hashCode(); rval += serverPortString.hashCode(); rval += serverLocation.hashCode(); rval += serverProtocol.hashCode(); rval += serverUserName.hashCode(); rval += password.hashCode(); return rval; } public boolean equals(Object o) { if (!(o instanceof AuthorizationResponseDescription)) return false; AuthorizationResponseDescription ard = (AuthorizationResponseDescription)o; if (!ard.userName.equals(userName)) return false; if (!ard.serverName.equals(serverName)) return false; if (!ard.serverPortString.equals(serverPortString)) return false; if (!ard.serverLocation.equals(serverLocation)) return false; if (!ard.serverProtocol.equals(serverProtocol)) return false; if (!ard.serverUserName.equals(serverUserName)) return false; if (!ard.password.equals(password)) return false; return true; } } }