package com.appian.integration.sharepoint; import com.appian.integration.restClientUtils.Utils.ContentManager; import com.appian.integration.sharepoint.exception.CustomRuntimeException; import com.appiancorp.type.json.parsers.JsonParserFactory; import com.google.common.net.MediaType; import java.io.*; import java.net.URI; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.*; import org.apache.commons.io.IOUtils; import org.apache.http.*; import org.apache.http.auth.AuthScope; import org.apache.http.auth.NTCredentials; import org.apache.http.client.*; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.*; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.client.utils.URIUtils; import org.apache.http.conn.ssl.*; import org.apache.http.entity.FileEntity; import org.apache.http.entity.StringEntity; import org.apache.http.impl.auth.BasicScheme; import org.apache.http.impl.client.*; import org.apache.http.message.BasicHeader; import org.apache.http.util.EntityUtils; import org.apache.log4j.Logger; // Referenced classes of package com.appian.integration.sharepoint: // SharepointIntegrationHandler, SharepointConnection, SharepointInput, SharepointHeaders public class SharepointIntegrationHandlerImpl implements SharepointIntegrationHandler { private static final String ATTACHMENT = "attachment"; private static final String FILENAME = "filename"; private static final String GET = "GET"; private static final String POST = "POST"; private static final String PUT = "PUT"; private static final String DELETE = "DELETE"; private static final String MERGE = "MERGE"; private static final Logger LOG = Logger.getLogger(com/appian/integration/sharepoint/SharepointIntegrationHandlerImpl); private static final String QUERY_FOR_DIGEST = "/_api/contextinfo"; private static final String FORM_DIGEST_VALUE = "FormDigestValue"; public SharepointIntegrationHandlerImpl() { } public String invokeHandle(SharepointConnection connection, SharepointInput input) throws Exception { if(LOG.isDebugEnabled()) { LOG.debug("[SharePoint] setting up connection"); } HttpHost targetHost = URIUtils.extractHost(URI.create(input.getQueryUrl())); CloseableHttpClient httpclient = null; try { httpclient = getHttpClient(targetHost, connection); } catch(Exception e) { throw new CustomRuntimeException("Http client build error", e); } AuthCache authCache = new BasicAuthCache(); BasicScheme basicAuth = new BasicScheme(); authCache.put(targetHost, basicAuth); HttpClientContext localContext = HttpClientContext.create(); localContext.setAuthCache(authCache); HttpEntity entity = null; String outJson = input.getHttpMethod().toUpperCase(); byte byte0 = -1; switch(outJson.hashCode()) { case 70454: if(outJson.equals("GET")) { byte0 = 0; } break; case 2461856: if(outJson.equals("POST")) { byte0 = 1; } break; case 79599: if(outJson.equals("PUT")) { byte0 = 2; } break; case 2012838315: if(outJson.equals("DELETE")) { byte0 = 3; } break; case 73247768: if(outJson.equals("MERGE")) { byte0 = 4; } break; } switch(byte0) { case 0: // '\0' entity = sharePointGet(input.getQueryUrl(), targetHost, httpclient, localContext, connection.getRetries(), input.getHttpMethod().toUpperCase()); break; case 1: // '\001' case 2: // '\002' case 3: // '\003' case 4: // '\004' if(input.getInputData() == null) { throw new CustomRuntimeException("Request malformatted", "importParams argument is null; this is not allowed for POST, PUT, DELETE and MER" + "GE methods" ); } entity = sharePointPost(input.getQueryUrl(), targetHost, httpclient, localContext, connection.getRetries(), input.getInputData(), input.getHttpMethod().toUpperCase()); break; default: throw new CustomRuntimeException("Unsupported request", "HTTP method name unexpected"); } outJson = null; if(LOG.isDebugEnabled()) { LOG.debug("[SharePoint] getting response in json"); } if(entity != null && entity.getContent() != null) { outJson = streamToString(entity.getContent()); } EntityUtils.consume(entity); httpclient.close(); return outJson; } public static HttpEntity sharePointGet(String queryUrl, HttpHost targetHost, CloseableHttpClient httpclient, HttpClientContext localContext, int retries, String httpmethod) throws Exception { if(LOG.isDebugEnabled()) { LOG.debug((new StringBuilder()).append("[SharePoint] method request: ").append(httpmethod.toUpperCase()).toString()); } HttpGet httpget = new HttpGet(queryUrl); httpget.addHeader(new BasicHeader("Accept", SharepointHeaders.ACCEPT_JSON.getField())); CloseableHttpResponse response = executeHttpRequest(targetHost, httpclient, localContext, retries, httpget, httpmethod.toUpperCase()); HttpEntity entity = response.getEntity(); if(!validateResponseCode(response.getStatusLine())) { StringWriter writer = new StringWriter(); IOUtils.copy(entity.getContent(), writer); String detail = writer.toString(); throw new CustomRuntimeException(response.getStatusLine().getReasonPhrase(), (new StringBuilder()).append(response.getStatusLine().toString()).append(detail.isEmpty() ? "" : (new StringBuilder()).append(" , ").append(detail).toString()).toString()); } else { return entity; } } public static HttpEntity sharePointPost(String queryUrl, HttpHost targetHost, CloseableHttpClient httpclient, HttpClientContext localContext, int retries, String data, String httpmethod) throws Exception { if(LOG.isDebugEnabled()) { LOG.debug((new StringBuilder()).append("[SharePoint] method request: ").append(httpmethod.toUpperCase()).toString()); } CloseableHttpResponse response = null; HttpEntity entity = null; if(LOG.isDebugEnabled()) { LOG.debug("[SharePoint] getting RequestDigest to perform CRUD operation"); } HttpPost httppostDigest = new HttpPost("/_api/contextinfo"); httppostDigest.addHeader(new BasicHeader(SharepointHeaders.ACCEPT_JSON.getName(), SharepointHeaders.ACCEPT_JSON.getField())); response = executeHttpRequest(targetHost, httpclient, localContext, retries, httppostDigest, httpmethod.toUpperCase()); String digestValue = streamToString(response.getEntity().getContent()); if(digestValue != null && digestValue.contains("FormDigestValue")) { LinkedHashMap job = (LinkedHashMap)JsonParserFactory.fromJson(digestValue); String digest = (String)getFieldContentMap(job, "FormDigestValue"); HttpPost httppost = new HttpPost(queryUrl); httppost.addHeader(new BasicHeader("Accept", SharepointHeaders.ACCEPT_JSON.getField())); httppost.addHeader(new BasicHeader("Content-Type", SharepointHeaders.ACCEPT_JSON.getField())); httppost.addHeader(new BasicHeader("If-Match", SharepointHeaders.IF_MATCH.getField())); httppost.addHeader(new BasicHeader("X-Requested-With", MediaType.ANY_TYPE.toString())); httppost.addHeader(new BasicHeader(SharepointHeaders.X_REQUESTDIGEST.getName(), digest)); if(LOG.isDebugEnabled()) { LOG.debug("[SharePoint] executing CRUD operation"); } String s = httpmethod.toUpperCase(); byte byte0 = -1; switch(s.hashCode()) { case 2461856: if(s.equals("POST")) { byte0 = 0; } break; case 79599: if(s.equals("PUT")) { byte0 = 1; } break; case 2012838315: if(s.equals("DELETE")) { byte0 = 2; } break; case 73247768: if(s.equals("MERGE")) { byte0 = 3; } break; } switch(byte0) { default: throw new CustomRuntimeException("Request malformatted", "HTTP method name unexpected"); case 1: // '\001' case 2: // '\002' case 3: // '\003' httppost.addHeader(new BasicHeader(SharepointHeaders.X_HTTP_METHOD.getName(), httpmethod.toUpperCase())); // fall through case 0: // '\0' httppost.setEntity(new StringEntity(data.toString())); break; } response = executeHttpRequest(targetHost, httpclient, localContext, retries, httppost, httpmethod.toUpperCase()); entity = response.getEntity(); if(!validateResponseCode(response.getStatusLine())) { StringWriter writer = new StringWriter(); IOUtils.copy(entity.getContent(), writer); String detail = writer.toString(); throw new CustomRuntimeException(response.getStatusLine().getReasonPhrase(), (new StringBuilder()).append(response.getStatusLine().toString()).append(detail.isEmpty() ? "" : (new StringBuilder()).append(" , ").append(detail).toString()).toString()); } else { return entity; } } else { throw new CustomRuntimeException("Digest error", "Unable to retrieve RequestDigest from SharePoint to execute POST request"); } } private static Object getFieldContentMap(LinkedHashMap map, String field) { Object ret = null; for(Iterator i$ = map.entrySet().iterator(); i$.hasNext();) { java.util.Map.Entry entry = (java.util.Map.Entry)i$.next(); String key = (String)entry.getKey(); if(key.equals(field)) { return (String)entry.getValue(); } if(entry.getValue() instanceof LinkedHashMap) { ret = getFieldContentMap((LinkedHashMap)entry.getValue(), field); } if(ret != null) { return ret; } } return null; } private static CloseableHttpResponse executeHttpRequest(HttpHost targetHost, CloseableHttpClient httpclient, HttpClientContext localContext, int retries, Object httprequest, String method) throws Exception { if(LOG.isDebugEnabled()) { LOG.debug((new StringBuilder()).append("[SharePoint] executing request; number of retries: ").append(retries).toString()); } int retryCount = 0; CloseableHttpResponse response = null; boolean caught; if(retries > 0) { do { caught = false; try { response = getResponse(targetHost, httpclient, localContext, httprequest, method); } catch(Exception e) { caught = true; if(retries == retryCount + 1) { throw new CustomRuntimeException("End of retries", e); } } } while(caught && retryCount++ <= retries); } else { response = getResponse(targetHost, httpclient, localContext, httprequest, method); } return response; } private static CloseableHttpResponse getResponse(HttpHost targetHost, CloseableHttpClient httpclient, HttpClientContext localContext, Object httprequest, String method) throws IOException, ClientProtocolException { CloseableHttpResponse response; if(method.toUpperCase().equals("GET")) { response = httpclient.execute(targetHost, (HttpGet)httprequest, localContext); } else { response = httpclient.execute(targetHost, (HttpPost)httprequest, localContext); } return response; } public static String streamToString(InputStream is) throws Exception { StringBuilder sb; Exception exception; BufferedReader reader = new BufferedReader(new InputStreamReader(is)); sb = new StringBuilder(); String line = null; try { while((line = reader.readLine()) != null) { sb.append((new StringBuilder()).append(line).append("\n").toString()); } } catch(IOException e) { throw new CustomRuntimeException("Convertion error", e); } finally { } try { is.close(); } catch(IOException e) { throw new CustomRuntimeException("Convertion error", e); } break MISSING_BLOCK_LABEL_123; try { is.close(); } catch(IOException e) { throw new CustomRuntimeException("Convertion error", e); } throw exception; return sb.toString(); } public String downloadFileHandle(SharepointConnection connection, String queryUrl, String dirInternalId, String fileName, ContentManager contentManager) throws Exception { if(LOG.isDebugEnabled()) { LOG.debug("[SharePoint] setting connection"); } RequestConfig defaultRequestConfig = RequestConfig.custom().setSocketTimeout(connection.getTimeout()).setConnectTimeout(connection.getTimeout()).setConnectionRequestTimeout(connection.getTimeout()).build(); String responseString = null; try { HttpGet request = new HttpGet(new URI(queryUrl)); request.addHeader("binaryStringResponseBody", "true"); if(LOG.isDebugEnabled()) { LOG.debug("[SharePoint] retrieving file"); } HttpHost targetHost = URIUtils.extractHost(URI.create(queryUrl)); CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()), new NTCredentials(connection.getUsername(), connection.getPassword(), "", connection.getDomain())); CloseableHttpClient httpclient = null; try { httpclient = getHttpClient(targetHost, connection); } catch(Exception e) { throw new CustomRuntimeException("Http client build error", e); } AuthCache authCache = new BasicAuthCache(); BasicScheme basicAuth = new BasicScheme(); authCache.put(targetHost, basicAuth); HttpClientContext localContext = HttpClientContext.create(); localContext.setAuthCache(authCache); HttpResponse response = executeHttpRequest(targetHost, httpclient, localContext, connection.getRetries(), request, "GET"); if(response != null) { HttpEntity entity = response.getEntity(); if(!validateResponseCode(response.getStatusLine())) { String detail = (new StringBuilder()).append("Attempting to retrieve file: ").append(fileName).toString(); throw new CustomRuntimeException(response.getStatusLine().getReasonPhrase(), (new StringBuilder()).append(response.getStatusLine().toString()).append(detail.isEmpty() ? "" : (new StringBuilder()).append(" , ").append(detail).toString()).toString()); } contentManager.executeDownload(entity.getContent(), fileName, dirInternalId); EntityUtils.consume(entity); } else { throw new CustomRuntimeException("Error getting file", "null or empty response"); } } catch(CustomRuntimeException e) { throw new CustomRuntimeException(e); } catch(Exception e) { throw new CustomRuntimeException("Error getting file", e.getMessage(), e); } return responseString; } public String uploadFileHandle(SharepointConnection connection, String queryUrl, String fileInternalId, ContentManager contentManager) throws Exception { if(LOG.isDebugEnabled()) { LOG.debug("[SharePoint]upload request "); } HttpHost targetHost = URIUtils.extractHost(URI.create(queryUrl)); CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()), new NTCredentials(connection.getUsername(), connection.getPassword(), "", connection.getDomain())); RequestConfig defaultRequestConfig = RequestConfig.custom().setSocketTimeout(connection.getTimeout()).setConnectTimeout(connection.getTimeout()).setConnectionRequestTimeout(connection.getTimeout()).build(); CloseableHttpClient httpclient = null; try { httpclient = getHttpClient(targetHost, connection); } catch(Exception e) { throw new CustomRuntimeException("Http client build error", e); } AuthCache authCache = new BasicAuthCache(); BasicScheme basicAuth = new BasicScheme(); authCache.put(targetHost, basicAuth); HttpClientContext localContext = HttpClientContext.create(); localContext.setAuthCache(authCache); HttpEntity entity = null; StringWriter writer = null; CloseableHttpResponse response = null; HttpPost httppostDigest = new HttpPost("/_api/contextinfo"); httppostDigest.addHeader(new BasicHeader(SharepointHeaders.ACCEPT_JSON.getName(), SharepointHeaders.ACCEPT_JSON.getField())); response = executeHttpRequest(targetHost, httpclient, localContext, connection.getRetries(), httppostDigest, "POST"); String digestValue = streamToString(response.getEntity().getContent()); if(digestValue != null && digestValue.contains("FormDigestValue")) { LinkedHashMap job = (LinkedHashMap)JsonParserFactory.fromJson(digestValue); String digest = (String)getFieldContentMap(job, "FormDigestValue"); File f = contentManager.getFileToUpload(fileInternalId); if(f == null) { throw new CustomRuntimeException("File error", (new StringBuilder()).append("fileInternalId ").append(fileInternalId).append(" not found").toString()); } HttpPost httppost = new HttpPost(queryUrl); httppost.addHeader(new BasicHeader("Accept", SharepointHeaders.ACCEPT_JSON.getField())); httppost.addHeader(new BasicHeader("Content-Type", SharepointHeaders.ACCEPT_JSON.getField())); httppost.addHeader(new BasicHeader("If-Match", SharepointHeaders.IF_MATCH.getField())); httppost.addHeader(new BasicHeader("X-Requested-With", MediaType.ANY_TYPE.toString())); httppost.addHeader(new BasicHeader(SharepointHeaders.X_REQUESTDIGEST.getName(), digest)); httppost.addHeader(new BasicHeader(SharepointHeaders.X_HTTP_METHOD.getName(), "POST")); httppost.setEntity(new FileEntity(f)); response = executeHttpRequest(targetHost, httpclient, localContext, connection.getRetries(), httppost, "POST"); if(response != null) { entity = response.getEntity(); writer = new StringWriter(); IOUtils.copy(entity.getContent(), writer); if(!validateResponseCode(response.getStatusLine())) { String detail = writer.toString(); throw new CustomRuntimeException(response.getStatusLine().getReasonPhrase(), (new StringBuilder()).append(response.getStatusLine().toString()).append(detail.isEmpty() ? "" : (new StringBuilder()).append(" , ").append(detail).toString()).toString()); } } else { throw new CustomRuntimeException("Error occours on uploading file", "null or empty response"); } } else { throw new CustomRuntimeException("Digest Error", "Unable to retrieve RequestDigest from SharePoint to execute POST request"); } String outJson = null; if(LOG.isDebugEnabled()) { LOG.debug("[SharePoint] getting response in json"); } if(entity != null && entity.getContent() != null) { outJson = streamToString(new StringBufferInputStream(writer.toString())); } EntityUtils.consume(entity); httpclient.close(); return outJson; } private CloseableHttpClient getHttpClient(HttpHost targetHost, SharepointConnection connection) throws Exception { CloseableHttpClient httpclient = null; CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()), new NTCredentials(connection.getUsername(), connection.getPassword(), "", connection.getDomain())); RequestConfig defaultRequestConfig = RequestConfig.custom().setSocketTimeout(connection.getTimeout()).setConnectTimeout(connection.getTimeout()).setConnectionRequestTimeout(connection.getTimeout()).build(); if(targetHost.getSchemeName().equals("http")) { httpclient = HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig).setDefaultCredentialsProvider(credsProvider).build(); } else if(targetHost.getSchemeName().equals("https")) { SSLContextBuilder builder = new SSLContextBuilder(); builder.loadTrustMaterial(null, new TrustStrategy() { final SharepointIntegrationHandlerImpl this$0; public boolean isTrusted(X509Certificate arg0[], String arg1) throws CertificateException { return true; } { this$0 = SharepointIntegrationHandlerImpl.this; super(); } }); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(), new AllowAllHostnameVerifier()); httpclient = HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig).setDefaultCredentialsProvider(credsProvider).setSSLSocketFactory(sslsf).build(); } else { throw new Exception((new StringBuilder()).append("Unsupported schema type: ").append(targetHost.getSchemeName()).toString()); } return httpclient; } private static boolean validateResponseCode(StatusLine statusResponse) { boolean result = false; if(statusResponse != null) { switch(statusResponse.getStatusCode()) { case 200: case 201: case 202: case 203: case 204: case 205: case 206: case 207: result = true; break; } } return result; } }