blob: c1cf4513ed407dca8e123fda41a9c964bcd5d7a8 [file] [log] [blame]
/* $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 SharePointRESTAuthority 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 SharePointRESTAuthority()
{
}
/** 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.getParameter(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.getParameter(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(60000);
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;
}
}
}