diff --git a/source/java/org/alfresco/repo/remoteconnector/RemoteConnectorServiceImpl.java b/source/java/org/alfresco/repo/remoteconnector/RemoteConnectorServiceImpl.java
index 7bc43de5f4..9539d97e20 100644
--- a/source/java/org/alfresco/repo/remoteconnector/RemoteConnectorServiceImpl.java
+++ b/source/java/org/alfresco/repo/remoteconnector/RemoteConnectorServiceImpl.java
@@ -1,547 +1,469 @@
-/*
- * #%L
- * Alfresco Repository
- * %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
- * %%
- * This file is part of the Alfresco software.
- * If the software was purchased under a paid Alfresco license, the terms of
- * the paid license agreement will prevail. Otherwise, the software is
- * provided under the following open source license terms:
- *
- * Alfresco is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Alfresco is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Alfresco. If not, see .
- * #L%
- */
-package org.alfresco.repo.remoteconnector;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.StringTokenizer;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.alfresco.repo.content.MimetypeMap;
-import org.alfresco.repo.security.authentication.AuthenticationException;
-import org.alfresco.service.cmr.remoteconnector.RemoteConnectorClientException;
-import org.alfresco.service.cmr.remoteconnector.RemoteConnectorRequest;
-import org.alfresco.service.cmr.remoteconnector.RemoteConnectorResponse;
-import org.alfresco.service.cmr.remoteconnector.RemoteConnectorServerException;
-import org.alfresco.service.cmr.remoteconnector.RemoteConnectorService;
-import org.alfresco.util.HttpClientHelper;
-import org.apache.commons.httpclient.Credentials;
-import org.apache.commons.httpclient.Header;
-import org.apache.commons.httpclient.HttpClient;
-import org.apache.commons.httpclient.HttpMethodBase;
-import org.apache.commons.httpclient.ProxyHost;
-import org.apache.commons.httpclient.UsernamePasswordCredentials;
-import org.apache.commons.httpclient.auth.AuthScope;
-import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
-import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
-import org.apache.commons.httpclient.methods.StringRequestEntity;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.json.simple.JSONObject;
-import org.json.simple.parser.JSONParser;
-import org.json.simple.parser.ParseException;
-import org.springframework.extensions.webscripts.Status;
-
-import static org.alfresco.service.cmr.favourites.FavouritesService.SortFields.username;
-
-/**
- * HttpClient powered implementation of {@link RemoteConnectorService}, which
- * performs requests to remote HTTP servers.
- *
- * Note - this class assumes direct connectivity is available to the destination
- * system, and does not support proxies.
- *
- * @author Nick Burch
- * @since 4.0.2
- */
-public class RemoteConnectorServiceImpl implements RemoteConnectorService
-{
- /**
- * The logger
- */
- private static Log logger = LogFactory.getLog(RemoteConnectorServiceImpl.class);
- private static final long MAX_BUFFER_RESPONSE_SIZE = 10*1024*1024;
-
- private static ProxyHost httpProxyHost;
- private static ProxyHost httpsProxyHost;
- private static Credentials httpProxyCredentials;
- private static Credentials httpsProxyCredentials;
- private static AuthScope httpAuthScope;
- private static AuthScope httpsAuthScope;
-
- /**
- * Initialise the HTTP Proxy Hosts and Params Factory
- */
- static
- {
- // Create an HTTP Proxy Host if appropriate system property set
- httpProxyHost = createProxyHost("http.proxyHost", "http.proxyPort", 80);
- httpProxyCredentials = createProxyCredentials("http.proxyUser", "http.proxyPassword");
- httpAuthScope = createProxyAuthScope(httpProxyHost);
-
- // Create an HTTPS Proxy Host if appropriate system property set
- httpsProxyHost = createProxyHost("https.proxyHost", "https.proxyPort", 443);
- httpsProxyCredentials = createProxyCredentials("https.proxyUser", "https.proxyPassword");
- httpsAuthScope = createProxyAuthScope(httpsProxyHost);
-
-
- }
-
- public RemoteConnectorServiceImpl()
- {}
-
- /**
- * Builds a new Request object
- */
- public RemoteConnectorRequest buildRequest(String url, String method)
- {
- return new RemoteConnectorRequestImpl(url, method);
- }
-
- /**
- * Builds a new Request object, using HttpClient method descriptions
- */
- public RemoteConnectorRequest buildRequest(String url, Class extends HttpMethodBase> method)
- {
- return new RemoteConnectorRequestImpl(url, method);
- }
-
- /**
- * Executes the specified request, and return the response
- */
- public RemoteConnectorResponse executeRequest(RemoteConnectorRequest request) throws IOException, AuthenticationException,
- RemoteConnectorClientException, RemoteConnectorServerException
- {
- RemoteConnectorRequestImpl reqImpl = (RemoteConnectorRequestImpl)request;
- HttpMethodBase httpRequest = reqImpl.getMethodInstance();
-
- // Attach the headers to the request
- for (Header hdr : request.getRequestHeaders())
- {
- httpRequest.addRequestHeader(hdr);
- }
-
- // Attach the body, if possible
- if (httpRequest instanceof EntityEnclosingMethod)
- {
- if (request.getRequestBody() != null)
- {
- ((EntityEnclosingMethod)httpRequest).setRequestEntity( reqImpl.getRequestBody() );
- }
- }
-
- // Grab our thread local HttpClient instance
- // Remember - we must then clean it up!
- HttpClient httpClient = HttpClientHelper.getHttpClient();
-
- // The url should already be vetted by the RemoteConnectorRequest
- URL url = new URL(request.getURL());
-
- // Use the appropriate Proxy Host if required
- if (httpProxyHost != null && url.getProtocol().equals("http") && requiresProxy(url.getHost()))
- {
- httpClient.getHostConfiguration().setProxyHost(httpProxyHost);
- if (logger.isDebugEnabled())
- logger.debug(" - using HTTP proxy host for: " + url);
- if (httpProxyCredentials != null)
- {
- httpClient.getState().setProxyCredentials(httpAuthScope, httpProxyCredentials);
- if (logger.isDebugEnabled())
- logger.debug(" - using HTTP proxy credentials for proxy: " + httpProxyHost.getHostName());
- }
- }
- else if (httpsProxyHost != null && url.getProtocol().equals("https") && requiresProxy(url.getHost()))
- {
- httpClient.getHostConfiguration().setProxyHost(httpsProxyHost);
- if (logger.isDebugEnabled())
- logger.debug(" - using HTTPS proxy host for: " + url);
- if (httpsProxyCredentials != null)
- {
- httpClient.getState().setProxyCredentials(httpsAuthScope, httpsProxyCredentials);
- if (logger.isDebugEnabled())
- logger.debug(" - using HTTPS proxy credentials for proxy: " + httpsProxyHost.getHostName());
- }
- }
- else
- {
- //host should not be proxied remove any configured proxies
- httpClient.getHostConfiguration().setProxyHost(null);
- httpClient.getState().clearProxyCredentials();
- }
-
- // Log what we're doing
- if (logger.isDebugEnabled()) {
- logger.debug("Performing " + request.getMethod() + " request to " + request.getURL());
- for (Header hdr : request.getRequestHeaders())
- {
- logger.debug("Header: " + hdr );
- }
- Object requestBody = null;
- if (request != null)
- {
- requestBody = request.getRequestBody();
- }
- if (requestBody != null && requestBody instanceof StringRequestEntity)
- {
- StringRequestEntity re = (StringRequestEntity)request.getRequestBody();
- // remove credentials from logs, such as "username":"John.Doe@test.com" and "password":"123456abc"
- // the strings can include double quotes, therefore we should check for proper end, it can be either
- // a comma "," or "}"
- // REPO-1471
- String payload = re.getContent(); // returns a new string, should be safe to modify
- String usernameString = "\"username\"";
- String passwordString = "\"password\"";
- String hiddenString = "\"\"";
- List matches = new LinkedList<>();
- Matcher m = Pattern.compile(usernameString + ":\"(.+)\",|" +
- usernameString + ":\"(.+)\"}|" +
- passwordString + ":\"(.+)\",|" +
- passwordString + ":\"(.+)\"}").matcher(payload);
- while(m.find())
- {
- matches.add(m.group());
- }
- for (String match: matches)
- {
- if (match.contains(usernameString))
- {
- payload = payload.replace(
- match.substring(
- match.indexOf(usernameString) + usernameString.length() + 1, // 1 is semicolon
- match.lastIndexOf("\"") + 1), // 1 is a double quote
- hiddenString);
- }
- else if (match.contains(passwordString))
- {
- payload = payload.replace(
- match.substring(
- match.indexOf(passwordString) + passwordString.length() + 1, // 1 is semicolon
- match.lastIndexOf("\"") + 1), // 1 is a double quote
- hiddenString);
- }
-
- }
-
- logger.debug("Payload (string): " + payload);
- }
- else if (requestBody != null && requestBody instanceof ByteArrayRequestEntity)
- {
- ByteArrayRequestEntity re = (ByteArrayRequestEntity)request.getRequestBody();
- logger.debug("Payload (byte array): " + re.getContent().toString());
- }
- else
- {
- logger.debug("Payload is not of a readable type.");
- }
- }
-
- // Perform the request, and wrap the response
- int status = -1;
- String statusText = null;
- RemoteConnectorResponse response = null;
- try
- {
- status = httpClient.executeMethod(httpRequest);
- statusText = httpRequest.getStatusText();
-
- Header[] responseHdrs = httpRequest.getResponseHeaders();
- Header responseContentTypeH = httpRequest.getResponseHeader(RemoteConnectorRequestImpl.HEADER_CONTENT_TYPE);
- String responseCharSet = httpRequest.getResponseCharSet();
- String responseContentType = (responseContentTypeH != null ? responseContentTypeH.getValue() : null);
-
- if(logger.isDebugEnabled())
- {
- logger.debug("response url=" + request.getURL() + ", length =" + httpRequest.getResponseContentLength() + ", responceContentType " + responseContentType + ", statusText =" + statusText );
- }
-
- // Decide on how best to handle the response, based on the size
- // Ideally, we want to close the HttpClient resources immediately, but
- // that isn't possible for very large responses
- // If we can close immediately, it makes cleanup simpler and fool-proof
- if (httpRequest.getResponseContentLength() > MAX_BUFFER_RESPONSE_SIZE || httpRequest.getResponseContentLength() == -1 )
- {
- if(logger.isTraceEnabled())
- {
- logger.trace("large response (or don't know length) url=" + request.getURL());
- }
-
- // Need to wrap the InputStream in something that'll close
- InputStream wrappedStream = new HttpClientReleasingInputStream(httpRequest);
- httpRequest = null;
-
- // Now build the response
- response = new RemoteConnectorResponseImpl(request, responseContentType, responseCharSet,
- status, responseHdrs, wrappedStream);
- }
- else
- {
- if(logger.isTraceEnabled())
- {
- logger.debug("small response for url=" + request.getURL());
- }
- // Fairly small response, just keep the bytes and make life simple
- response = new RemoteConnectorResponseImpl(request, responseContentType, responseCharSet,
- status, responseHdrs, httpRequest.getResponseBody());
-
- // Now we have the bytes, we can close the HttpClient resources
- httpRequest.releaseConnection();
- httpRequest = null;
- }
- }
- finally
- {
- // Make sure, problems or not, we always tidy up (if not large stream based)
- // This is important because we use a thread local HttpClient instance
- if (httpRequest != null)
- {
- httpRequest.releaseConnection();
- httpRequest = null;
- }
- }
-
-
- // Log the response
- if (logger.isDebugEnabled())
- logger.debug("Response was " + status + " " + statusText);
-
- // Decide if we should throw an exception
- if (status >= 300)
- {
- // Tidy if needed
- if (httpRequest != null)
- httpRequest.releaseConnection();
-
- // Specific exceptions
- if (status == Status.STATUS_FORBIDDEN ||
- status == Status.STATUS_UNAUTHORIZED)
- {
- // TODO Forbidden may need to be handled differently.
- // TODO Need to get error message into the AuthenticationException
- throw new AuthenticationException(statusText);
- }
-
- // Server side exceptions
- if (status >= 500 && status <= 599)
- {
- logger.error("executeRequest: remote connector server exception: ["+status+"] "+statusText);
- throw new RemoteConnectorServerException(status, statusText);
- }
- if(status == Status.STATUS_PRECONDITION_FAILED)
- {
- logger.error("executeRequest: remote connector client exception: ["+status+"] "+statusText);
- throw new RemoteConnectorClientException(status, statusText, response);
- }
- else
- {
- // Client request exceptions
- if (httpRequest != null)
- {
- // Response wasn't too big and is available, supply it
- logger.error("executeRequest: remote connector client exception: ["+status+"] "+statusText);
- throw new RemoteConnectorClientException(status, statusText, response);
- }
- else
- {
- // Response was too large, report without it
- logger.error("executeRequest: remote connector client exception: ["+status+"] "+statusText);
- throw new RemoteConnectorClientException(status, statusText, null);
- }
- }
- }
-
- // If we get here, then the request/response was all fine
- // So, return our created response
- return response;
- }
-
- /**
- * Executes the given request, requesting a JSON response, and
- * returns the parsed JSON received back
- *
- * @throws ParseException If the response is not valid JSON
- */
- public JSONObject executeJSONRequest(RemoteConnectorRequest request) throws ParseException, IOException, AuthenticationException
- {
- return doExecuteJSONRequest(request, this);
- }
-
- public static JSONObject doExecuteJSONRequest(RemoteConnectorRequest request, RemoteConnectorService service) throws ParseException, IOException, AuthenticationException
- {
- // Set as JSON
- request.setContentType(MimetypeMap.MIMETYPE_JSON);
-
- // Perform the request
- RemoteConnectorResponse response = service.executeRequest(request);
-
- // Parse this as JSON
- JSONParser parser = new JSONParser();
- String jsonText = response.getResponseBodyAsString();
- Object json = parser.parse(jsonText);
-
- // Check it's the right type and return
- if (json instanceof JSONObject)
- {
- return (JSONObject)json;
- }
- else
- {
- throw new ParseException(0, json);
- }
- }
-
- private static class HttpClientReleasingInputStream extends FilterInputStream
- {
- private HttpMethodBase httpRequest;
- private HttpClientReleasingInputStream(HttpMethodBase httpRequest) throws IOException
- {
- super(httpRequest.getResponseBodyAsStream());
- this.httpRequest = httpRequest;
- }
-
- @Override
- public void close() throws IOException
- {
- // Tidy the main stream
- super.close();
-
- // Now release the underlying resources
- if (httpRequest != null)
- {
- httpRequest.releaseConnection();
- httpRequest = null;
- }
- }
-
- /**
- * In case the caller has neglected to close the Stream, warn
- * (as this will break things for other users!) and then close
- */
- @Override
- protected void finalize() throws Throwable
- {
- if (httpRequest != null)
- {
- logger.warn("RemoteConnector response InputStream wasn't closed but must be! This can cause issues for " +
- "other requests in this Thread!");
-
- httpRequest.releaseConnection();
- httpRequest = null;
- }
-
- // Let the InputStream tidy up if it wants to too
- super.finalize();
- }
- }
-
- /**
- * Create proxy host for the given system host and port properties.
- * If the properties are not set, no proxy will be created.
- *
- * @param hostProperty String
- * @param portProperty String
- * @param defaultPort int
- *
- * @return ProxyHost if appropriate properties have been set, null otherwise
- */
- private static ProxyHost createProxyHost(final String hostProperty, final String portProperty, final int defaultPort)
- {
- final String proxyHost = System.getProperty(hostProperty);
- ProxyHost proxy = null;
- if (proxyHost != null && proxyHost.length() != 0)
- {
- final String strProxyPort = System.getProperty(portProperty);
- if (strProxyPort == null || strProxyPort.length() == 0)
- {
- proxy = new ProxyHost(proxyHost, defaultPort);
- }
- else
- {
- proxy = new ProxyHost(proxyHost, Integer.parseInt(strProxyPort));
- }
- if (logger.isDebugEnabled())
- logger.debug("ProxyHost: " + proxy.toString());
- }
- return proxy;
- }
-
- /**
- * Create the proxy credentials for the given proxy user and password properties.
- * If the properties are not set, not credentials will be created.
- * @param proxyUserProperty String
- * @param proxyPasswordProperty String
- * @return Credentials if appropriate properties have been set, null otherwise
- */
- private static Credentials createProxyCredentials(final String proxyUserProperty, final String proxyPasswordProperty)
- {
- final String proxyUser = System.getProperty(proxyUserProperty);
- final String proxyPassword = System.getProperty(proxyPasswordProperty);
- Credentials creds = null;
- if (StringUtils.isNotBlank(proxyUser))
- {
- creds = new UsernamePasswordCredentials(proxyUser, proxyPassword);
- }
- return creds;
- }
-
- /**
- * Create suitable AuthScope for ProxyHost.
- * If the ProxyHost is null, no AuthsScope will be created.
- * @param proxyHost ProxyHost
- * @return Authscope for provided ProxyHost, null otherwise.
- */
- private static AuthScope createProxyAuthScope(final ProxyHost proxyHost)
- {
- AuthScope authScope = null;
- if (proxyHost != null)
- {
- authScope = new AuthScope(proxyHost.getHostName(), proxyHost.getPort());
- }
- return authScope;
- }
-
- /**
- * Return true unless the given target host is specified in the http.nonProxyHosts
system property.
- * See http://download.oracle.com/javase/1.4.2/docs/guide/net/properties.html
- * @param targetHost Non-null host name to test
- * @return true if not specified in list, false if it is specifed and therefore should be excluded from proxy
- */
- private boolean requiresProxy(final String targetHost)
- {
- boolean requiresProxy = true;
- final String nonProxyHosts = System.getProperty("http.nonProxyHosts");
- if (nonProxyHosts != null)
- {
- StringTokenizer tokenizer = new StringTokenizer(nonProxyHosts, "|");
- while (tokenizer.hasMoreTokens())
- {
- String pattern = tokenizer.nextToken();
- pattern = pattern.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*");
- if (targetHost.matches(pattern))
- {
- requiresProxy = false;
- break;
- }
- }
- }
- return requiresProxy;
- }
-}
+/*
+ * #%L
+ * Alfresco Repository
+ * %%
+ * Copyright (C) 2005 - 2017 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.repo.remoteconnector;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.alfresco.repo.content.MimetypeMap;
+import org.alfresco.repo.security.authentication.AuthenticationException;
+import org.alfresco.service.cmr.remoteconnector.RemoteConnectorClientException;
+import org.alfresco.service.cmr.remoteconnector.RemoteConnectorRequest;
+import org.alfresco.service.cmr.remoteconnector.RemoteConnectorResponse;
+import org.alfresco.service.cmr.remoteconnector.RemoteConnectorServerException;
+import org.alfresco.service.cmr.remoteconnector.RemoteConnectorService;
+import org.alfresco.util.HttpClientHelper;
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethodBase;
+import org.apache.commons.httpclient.ProxyHost;
+import org.apache.commons.httpclient.auth.AuthScope;
+import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
+import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.springframework.extensions.webscripts.Status;
+
+/**
+ * HttpClient powered implementation of {@link RemoteConnectorService}, which performs requests to remote HTTP servers.
+ *
+ * @author Nick Burch
+ * @since 4.0.2
+ */
+public class RemoteConnectorServiceImpl implements RemoteConnectorService
+{
+ /**
+ * The logger
+ */
+ private static Log logger = LogFactory.getLog(RemoteConnectorServiceImpl.class);
+ private static final long MAX_BUFFER_RESPONSE_SIZE = 10*1024*1024;
+
+ private static ProxyHost httpProxyHost;
+ private static ProxyHost httpsProxyHost;
+ private static Credentials httpProxyCredentials;
+ private static Credentials httpsProxyCredentials;
+ private static AuthScope httpAuthScope;
+ private static AuthScope httpsAuthScope;
+
+ /**
+ * Initialise the HTTP Proxy Hosts and Params Factory
+ */
+ static
+ {
+ // Create an HTTP Proxy Host if appropriate system property set
+ httpProxyHost = HttpClientHelper.createProxyHost("http.proxyHost", "http.proxyPort", 80);
+ httpProxyCredentials = HttpClientHelper.createProxyCredentials("http.proxyUser", "http.proxyPassword");
+ httpAuthScope = createProxyAuthScope(httpProxyHost);
+
+ // Create an HTTPS Proxy Host if appropriate system property set
+ httpsProxyHost = HttpClientHelper.createProxyHost("https.proxyHost", "https.proxyPort", 443);
+ httpsProxyCredentials = HttpClientHelper.createProxyCredentials("https.proxyUser", "https.proxyPassword");
+ httpsAuthScope = createProxyAuthScope(httpsProxyHost);
+ }
+
+ public RemoteConnectorServiceImpl()
+ {}
+
+ /**
+ * Builds a new Request object
+ */
+ public RemoteConnectorRequest buildRequest(String url, String method)
+ {
+ return new RemoteConnectorRequestImpl(url, method);
+ }
+
+ /**
+ * Builds a new Request object, using HttpClient method descriptions
+ */
+ public RemoteConnectorRequest buildRequest(String url, Class extends HttpMethodBase> method)
+ {
+ return new RemoteConnectorRequestImpl(url, method);
+ }
+
+ /**
+ * Executes the specified request, and return the response
+ */
+ public RemoteConnectorResponse executeRequest(RemoteConnectorRequest request) throws IOException, AuthenticationException,
+ RemoteConnectorClientException, RemoteConnectorServerException
+ {
+ RemoteConnectorRequestImpl reqImpl = (RemoteConnectorRequestImpl)request;
+ HttpMethodBase httpRequest = reqImpl.getMethodInstance();
+
+ // Attach the headers to the request
+ for (Header hdr : request.getRequestHeaders())
+ {
+ httpRequest.addRequestHeader(hdr);
+ }
+
+ // Attach the body, if possible
+ if (httpRequest instanceof EntityEnclosingMethod)
+ {
+ if (request.getRequestBody() != null)
+ {
+ ((EntityEnclosingMethod)httpRequest).setRequestEntity( reqImpl.getRequestBody() );
+ }
+ }
+
+ // Grab our thread local HttpClient instance
+ // Remember - we must then clean it up!
+ HttpClient httpClient = HttpClientHelper.getHttpClient();
+
+ // The url should already be vetted by the RemoteConnectorRequest
+ URL url = new URL(request.getURL());
+
+ // Use the appropriate Proxy Host if required
+ if (httpProxyHost != null && url.getProtocol().equals("http") && HttpClientHelper.requiresProxy(url.getHost()))
+ {
+ httpClient.getHostConfiguration().setProxyHost(httpProxyHost);
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(" - using HTTP proxy host for: " + url);
+ }
+ if (httpProxyCredentials != null)
+ {
+ httpClient.getState().setProxyCredentials(httpAuthScope, httpProxyCredentials);
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(" - using HTTP proxy credentials for proxy: " + httpProxyHost.getHostName());
+ }
+ }
+ }
+ else if (httpsProxyHost != null && url.getProtocol().equals("https") && HttpClientHelper.requiresProxy(url.getHost()))
+ {
+ httpClient.getHostConfiguration().setProxyHost(httpsProxyHost);
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(" - using HTTPS proxy host for: " + url);
+ }
+ if (httpsProxyCredentials != null)
+ {
+ httpClient.getState().setProxyCredentials(httpsAuthScope, httpsProxyCredentials);
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(" - using HTTPS proxy credentials for proxy: " + httpsProxyHost.getHostName());
+ }
+ }
+ }
+ else
+ {
+ //host should not be proxied remove any configured proxies
+ httpClient.getHostConfiguration().setProxyHost(null);
+ httpClient.getState().clearProxyCredentials();
+ }
+
+ // Log what we're doing
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Performing " + request.getMethod() + " request to " + request.getURL());
+ for (Header hdr : request.getRequestHeaders())
+ {
+ logger.debug("Header: " + hdr );
+ }
+ Object requestBody = null;
+ if (request != null)
+ {
+ requestBody = request.getRequestBody();
+ }
+ if (requestBody != null && requestBody instanceof StringRequestEntity)
+ {
+ StringRequestEntity re = (StringRequestEntity)request.getRequestBody();
+ // remove credentials from logs, such as "username":"John.Doe@test.com" and "password":"123456abc"
+ // the strings can include double quotes, therefore we should check for proper end, it can be either
+ // a comma "," or "}"
+ // REPO-1471
+ String payload = re.getContent(); // returns a new string, should be safe to modify
+ String usernameString = "\"username\"";
+ String passwordString = "\"password\"";
+ String hiddenString = "\"\"";
+ List matches = new LinkedList<>();
+ Matcher m = Pattern.compile(usernameString + ":\"(.+)\",|" +
+ usernameString + ":\"(.+)\"}|" +
+ passwordString + ":\"(.+)\",|" +
+ passwordString + ":\"(.+)\"}").matcher(payload);
+ while(m.find())
+ {
+ matches.add(m.group());
+ }
+ for (String match: matches)
+ {
+ if (match.contains(usernameString))
+ {
+ payload = payload.replace(
+ match.substring(
+ match.indexOf(usernameString) + usernameString.length() + 1, // 1 is semicolon
+ match.lastIndexOf("\"") + 1), // 1 is a double quote
+ hiddenString);
+ }
+ else if (match.contains(passwordString))
+ {
+ payload = payload.replace(
+ match.substring(
+ match.indexOf(passwordString) + passwordString.length() + 1, // 1 is semicolon
+ match.lastIndexOf("\"") + 1), // 1 is a double quote
+ hiddenString);
+ }
+
+ }
+
+ logger.debug("Payload (string): " + payload);
+ }
+ else if (requestBody != null && requestBody instanceof ByteArrayRequestEntity)
+ {
+ ByteArrayRequestEntity re = (ByteArrayRequestEntity)request.getRequestBody();
+ logger.debug("Payload (byte array): " + re.getContent().toString());
+ }
+ else
+ {
+ logger.debug("Payload is not of a readable type.");
+ }
+ }
+
+ // Perform the request, and wrap the response
+ int status = -1;
+ String statusText = null;
+ RemoteConnectorResponse response = null;
+ try
+ {
+ status = httpClient.executeMethod(httpRequest);
+ statusText = httpRequest.getStatusText();
+
+ Header[] responseHdrs = httpRequest.getResponseHeaders();
+ Header responseContentTypeH = httpRequest.getResponseHeader(RemoteConnectorRequestImpl.HEADER_CONTENT_TYPE);
+ String responseCharSet = httpRequest.getResponseCharSet();
+ String responseContentType = (responseContentTypeH != null ? responseContentTypeH.getValue() : null);
+
+ if(logger.isDebugEnabled())
+ {
+ logger.debug("response url=" + request.getURL() + ", length =" + httpRequest.getResponseContentLength() + ", responceContentType " + responseContentType + ", statusText =" + statusText );
+ }
+
+ // Decide on how best to handle the response, based on the size
+ // Ideally, we want to close the HttpClient resources immediately, but
+ // that isn't possible for very large responses
+ // If we can close immediately, it makes cleanup simpler and fool-proof
+ if (httpRequest.getResponseContentLength() > MAX_BUFFER_RESPONSE_SIZE || httpRequest.getResponseContentLength() == -1 )
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.trace("large response (or don't know length) url=" + request.getURL());
+ }
+
+ // Need to wrap the InputStream in something that'll close
+ InputStream wrappedStream = new HttpClientReleasingInputStream(httpRequest);
+ httpRequest = null;
+
+ // Now build the response
+ response = new RemoteConnectorResponseImpl(request, responseContentType, responseCharSet,
+ status, responseHdrs, wrappedStream);
+ }
+ else
+ {
+ if(logger.isTraceEnabled())
+ {
+ logger.debug("small response for url=" + request.getURL());
+ }
+ // Fairly small response, just keep the bytes and make life simple
+ response = new RemoteConnectorResponseImpl(request, responseContentType, responseCharSet,
+ status, responseHdrs, httpRequest.getResponseBody());
+
+ // Now we have the bytes, we can close the HttpClient resources
+ httpRequest.releaseConnection();
+ httpRequest = null;
+ }
+ }
+ finally
+ {
+ // Make sure, problems or not, we always tidy up (if not large stream based)
+ // This is important because we use a thread local HttpClient instance
+ if (httpRequest != null)
+ {
+ httpRequest.releaseConnection();
+ httpRequest = null;
+ }
+ }
+
+
+ // Log the response
+ if (logger.isDebugEnabled())
+ logger.debug("Response was " + status + " " + statusText);
+
+ // Decide if we should throw an exception
+ if (status >= 300)
+ {
+ // Tidy if needed
+ if (httpRequest != null)
+ httpRequest.releaseConnection();
+
+ // Specific exceptions
+ if (status == Status.STATUS_FORBIDDEN ||
+ status == Status.STATUS_UNAUTHORIZED)
+ {
+ // TODO Forbidden may need to be handled differently.
+ // TODO Need to get error message into the AuthenticationException
+ throw new AuthenticationException(statusText);
+ }
+
+ // Server side exceptions
+ if (status >= 500 && status <= 599)
+ {
+ logger.error("executeRequest: remote connector server exception: ["+status+"] "+statusText);
+ throw new RemoteConnectorServerException(status, statusText);
+ }
+ if(status == Status.STATUS_PRECONDITION_FAILED)
+ {
+ logger.error("executeRequest: remote connector client exception: ["+status+"] "+statusText);
+ throw new RemoteConnectorClientException(status, statusText, response);
+ }
+ else
+ {
+ // Client request exceptions
+ if (httpRequest != null)
+ {
+ // Response wasn't too big and is available, supply it
+ logger.error("executeRequest: remote connector client exception: ["+status+"] "+statusText);
+ throw new RemoteConnectorClientException(status, statusText, response);
+ }
+ else
+ {
+ // Response was too large, report without it
+ logger.error("executeRequest: remote connector client exception: ["+status+"] "+statusText);
+ throw new RemoteConnectorClientException(status, statusText, null);
+ }
+ }
+ }
+
+ // If we get here, then the request/response was all fine
+ // So, return our created response
+ return response;
+ }
+
+ /**
+ * Executes the given request, requesting a JSON response, and
+ * returns the parsed JSON received back
+ *
+ * @throws ParseException If the response is not valid JSON
+ */
+ public JSONObject executeJSONRequest(RemoteConnectorRequest request) throws ParseException, IOException, AuthenticationException
+ {
+ return doExecuteJSONRequest(request, this);
+ }
+
+ public static JSONObject doExecuteJSONRequest(RemoteConnectorRequest request, RemoteConnectorService service) throws ParseException, IOException, AuthenticationException
+ {
+ // Set as JSON
+ request.setContentType(MimetypeMap.MIMETYPE_JSON);
+
+ // Perform the request
+ RemoteConnectorResponse response = service.executeRequest(request);
+
+ // Parse this as JSON
+ JSONParser parser = new JSONParser();
+ String jsonText = response.getResponseBodyAsString();
+ Object json = parser.parse(jsonText);
+
+ // Check it's the right type and return
+ if (json instanceof JSONObject)
+ {
+ return (JSONObject)json;
+ }
+ else
+ {
+ throw new ParseException(0, json);
+ }
+ }
+
+ private static class HttpClientReleasingInputStream extends FilterInputStream
+ {
+ private HttpMethodBase httpRequest;
+ private HttpClientReleasingInputStream(HttpMethodBase httpRequest) throws IOException
+ {
+ super(httpRequest.getResponseBodyAsStream());
+ this.httpRequest = httpRequest;
+ }
+
+ @Override
+ public void close() throws IOException
+ {
+ // Tidy the main stream
+ super.close();
+
+ // Now release the underlying resources
+ if (httpRequest != null)
+ {
+ httpRequest.releaseConnection();
+ httpRequest = null;
+ }
+ }
+
+ /**
+ * In case the caller has neglected to close the Stream, warn
+ * (as this will break things for other users!) and then close
+ */
+ @Override
+ protected void finalize() throws Throwable
+ {
+ if (httpRequest != null)
+ {
+ logger.warn("RemoteConnector response InputStream wasn't closed but must be! This can cause issues for " +
+ "other requests in this Thread!");
+
+ httpRequest.releaseConnection();
+ httpRequest = null;
+ }
+
+ // Let the InputStream tidy up if it wants to too
+ super.finalize();
+ }
+ }
+
+ /**
+ * Create suitable AuthScope for ProxyHost.
+ * If the ProxyHost is null, no AuthsScope will be created.
+ * @param proxyHost ProxyHost
+ * @return Authscope for provided ProxyHost, null otherwise.
+ */
+ private static AuthScope createProxyAuthScope(final ProxyHost proxyHost)
+ {
+ AuthScope authScope = null;
+ if (proxyHost != null)
+ {
+ authScope = new AuthScope(proxyHost.getHostName(), proxyHost.getPort());
+ }
+ return authScope;
+ }
+
+}
diff --git a/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImpl.java b/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImpl.java
index 74d7b5ef41..5ddbe41b5d 100644
--- a/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImpl.java
+++ b/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImpl.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -23,128 +23,147 @@
* along with Alfresco. If not, see .
* #L%
*/
-
-package org.alfresco.repo.transfer;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.channels.Channels;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.WritableByteChannel;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-import org.alfresco.service.cmr.repository.AssociationRef;
-import org.alfresco.service.cmr.repository.ContentData;
-import org.alfresco.service.cmr.repository.ContentService;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.service.cmr.transfer.TransferException;
-import org.alfresco.service.cmr.transfer.TransferProgress;
-import org.alfresco.service.cmr.transfer.TransferTarget;
-import org.alfresco.service.cmr.transfer.TransferVersion;
-import org.alfresco.util.PropertyCheck;
-import org.alfresco.util.json.ExceptionJsonSerializer;
-import org.alfresco.util.json.JsonSerializer;
-import org.apache.commons.httpclient.HostConfiguration;
-import org.apache.commons.httpclient.HttpClient;
-import org.apache.commons.httpclient.HttpMethod;
-import org.apache.commons.httpclient.HttpState;
-import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
-import org.apache.commons.httpclient.NameValuePair;
-import org.apache.commons.httpclient.UsernamePasswordCredentials;
-import org.apache.commons.httpclient.auth.AuthScope;
-import org.apache.commons.httpclient.methods.PostMethod;
-import org.apache.commons.httpclient.methods.multipart.FilePart;
-import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
-import org.apache.commons.httpclient.methods.multipart.Part;
-import org.apache.commons.httpclient.protocol.DefaultProtocolSocketFactory;
-import org.apache.commons.httpclient.protocol.Protocol;
-import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
-import org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-/**
- * HTTP implementation of TransferTransmitter.
- *
- * Sends data via HTTP to the server.
- *
- * @author brian
- */
-public class HttpClientTransmitterImpl implements TransferTransmitter
-{
- private static final Log log = LogFactory.getLog(HttpClientTransmitterImpl.class);
-
- private static final String MSG_UNSUPPORTED_PROTOCOL = "transfer_service.comms.unsupported_protocol";
- private static final String MSG_UNSUCCESSFUL_RESPONSE = "transfer_service.comms.unsuccessful_response";
- private static final String MSG_HTTP_REQUEST_FAILED = "transfer_service.comms.http_request_failed";
-
- private static final int DEFAULT_HTTP_PORT = 80;
- private static final int DEFAULT_HTTPS_PORT = 443;
- private static final String HTTP_SCHEME_NAME = "http"; // lowercase is important
- private static final String HTTPS_SCHEME_NAME = "https"; // lowercase is important
-
- private HttpClient httpClient = null;
- private Protocol httpProtocol = new Protocol(HTTP_SCHEME_NAME, new DefaultProtocolSocketFactory(), DEFAULT_HTTP_PORT);
- private Protocol httpsProtocol = new Protocol(HTTPS_SCHEME_NAME, (ProtocolSocketFactory) new SSLProtocolSocketFactory(), DEFAULT_HTTPS_PORT);
- private Map protocolMap = null;
- private HttpMethodFactory httpMethodFactory = null;
- private JsonSerializer jsonErrorSerializer;
-
- private ContentService contentService;
-
- private NodeService nodeService;
+
+package org.alfresco.repo.transfer;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.alfresco.service.cmr.repository.AssociationRef;
+import org.alfresco.service.cmr.repository.ContentData;
+import org.alfresco.service.cmr.repository.ContentService;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.transfer.TransferException;
+import org.alfresco.service.cmr.transfer.TransferProgress;
+import org.alfresco.service.cmr.transfer.TransferTarget;
+import org.alfresco.service.cmr.transfer.TransferVersion;
+import org.alfresco.util.HttpClientHelper;
+import org.alfresco.util.PropertyCheck;
+import org.alfresco.util.json.ExceptionJsonSerializer;
+import org.alfresco.util.json.JsonSerializer;
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.HostConfiguration;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.HttpState;
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.ProxyHost;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.commons.httpclient.auth.AuthScope;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.multipart.FilePart;
+import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
+import org.apache.commons.httpclient.methods.multipart.Part;
+import org.apache.commons.httpclient.protocol.DefaultProtocolSocketFactory;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
+import org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.json.JSONObject;
+
+/**
+ * HTTP implementation of TransferTransmitter.
+ *
+ * Sends data via HTTP to the server.
+ *
+ * @author brian
+ */
+public class HttpClientTransmitterImpl implements TransferTransmitter
+{
+ private static final Log log = LogFactory.getLog(HttpClientTransmitterImpl.class);
+
+ private static final String MSG_UNSUPPORTED_PROTOCOL = "transfer_service.comms.unsupported_protocol";
+ private static final String MSG_UNSUCCESSFUL_RESPONSE = "transfer_service.comms.unsuccessful_response";
+ private static final String MSG_HTTP_REQUEST_FAILED = "transfer_service.comms.http_request_failed";
+
+ private static final int DEFAULT_HTTP_PORT = 80;
+ private static final int DEFAULT_HTTPS_PORT = 443;
+ private static final String HTTP_SCHEME_NAME = "http"; // lowercase is important
+ private static final String HTTPS_SCHEME_NAME = "https"; // lowercase is important
+
+ private HttpClient httpClient = null;
+ private Protocol httpProtocol = new Protocol(HTTP_SCHEME_NAME, new DefaultProtocolSocketFactory(), DEFAULT_HTTP_PORT);
+ private Protocol httpsProtocol = new Protocol(HTTPS_SCHEME_NAME, (ProtocolSocketFactory) new SSLProtocolSocketFactory(), DEFAULT_HTTPS_PORT);
+ private Map protocolMap = null;
+ private HttpMethodFactory httpMethodFactory = null;
+ private JsonSerializer jsonErrorSerializer;
+
+ private ContentService contentService;
+
+ private NodeService nodeService;
private boolean isAuthenticationPreemptive = false;
-
- public HttpClientTransmitterImpl()
- {
- protocolMap = new TreeMap();
- protocolMap.put(HTTP_SCHEME_NAME, httpProtocol);
- protocolMap.put(HTTPS_SCHEME_NAME, httpsProtocol);
-
- httpClient = new HttpClient();
- httpClient.setHttpConnectionManager(new MultiThreadedHttpConnectionManager());
- httpMethodFactory = new StandardHttpMethodFactoryImpl();
- jsonErrorSerializer = new ExceptionJsonSerializer();
- }
-
- public void init()
- {
- PropertyCheck.mandatory(this, "contentService", contentService);
+
+ private ProxyHost httpProxyHost;
+ private ProxyHost httpsProxyHost;
+ private Credentials httpProxyCredentials;
+ private Credentials httpsProxyCredentials;
+ private AuthScope httpAuthScope;
+ private AuthScope httpsAuthScope;
+
+ public HttpClientTransmitterImpl()
+ {
+ protocolMap = new TreeMap();
+ protocolMap.put(HTTP_SCHEME_NAME, httpProtocol);
+ protocolMap.put(HTTPS_SCHEME_NAME, httpsProtocol);
+
+ httpClient = new HttpClient();
+ httpClient.setHttpConnectionManager(new MultiThreadedHttpConnectionManager());
+ httpMethodFactory = new StandardHttpMethodFactoryImpl();
+ jsonErrorSerializer = new ExceptionJsonSerializer();
+
+ // Create an HTTP Proxy Host if appropriate system properties are set
+ httpProxyHost = HttpClientHelper.createProxyHost("http.proxyHost", "http.proxyPort", DEFAULT_HTTP_PORT);
+ httpProxyCredentials = HttpClientHelper.createProxyCredentials("http.proxyUser", "http.proxyPassword");
+ httpAuthScope = createProxyAuthScope(httpProxyHost);
+
+ // Create an HTTPS Proxy Host if appropriate system properties are set
+ httpsProxyHost = HttpClientHelper.createProxyHost("https.proxyHost", "https.proxyPort", DEFAULT_HTTPS_PORT);
+ httpsProxyCredentials = HttpClientHelper.createProxyCredentials("https.proxyUser", "https.proxyPassword");
+ httpsAuthScope = createProxyAuthScope(httpsProxyHost);
+ }
+
+ public void init()
+ {
+ PropertyCheck.mandatory(this, "contentService", contentService);
httpClient.getParams().setAuthenticationPreemptive(isAuthenticationPreemptive);
- }
-
- /**
- * By default this class uses the standard SSLProtocolSocketFactory, but this method allows this to be overridden.
- * Useful if, for example, one wishes to permit support of self-signed certificates on the target.
+ }
+
+ /**
+ * By default this class uses the standard SSLProtocolSocketFactory, but this method allows this to be overridden.
+ * Useful if, for example, one wishes to permit support of self-signed certificates on the target.
* @param socketFactory ProtocolSocketFactory
- */
- public void setHttpsSocketFactory(ProtocolSocketFactory socketFactory)
- {
- protocolMap.put(HTTPS_SCHEME_NAME, new Protocol(HTTPS_SCHEME_NAME, socketFactory, DEFAULT_HTTPS_PORT));
- }
-
- /**
- * By default, this class uses a plain HttpClient instance with the only non-default
- * option being the multi-threaded connection manager.
- * Use this method to replace this with your own HttpClient instance configured how you wish
+ */
+ public void setHttpsSocketFactory(ProtocolSocketFactory socketFactory)
+ {
+ protocolMap.put(HTTPS_SCHEME_NAME, new Protocol(HTTPS_SCHEME_NAME, socketFactory, DEFAULT_HTTPS_PORT));
+ }
+
+ /**
+ * By default, this class uses a plain HttpClient instance with the only non-default
+ * option being the multi-threaded connection manager.
+ * Use this method to replace this with your own HttpClient instance configured how you wish
* @param httpClient HttpClient
- */
- public void setHttpClient(HttpClient httpClient)
- {
- this.httpClient = httpClient;
- }
-
+ */
+ public void setHttpClient(HttpClient httpClient)
+ {
+ this.httpClient = httpClient;
+ }
+
/**
* Whether httpClient will use preemptive authentication or not.
* @param isAuthenticationPreemptive boolean
@@ -154,649 +173,725 @@ public class HttpClientTransmitterImpl implements TransferTransmitter
this.isAuthenticationPreemptive = isAuthenticationPreemptive;
}
- /* (non-Javadoc)
- * @see org.alfresco.repo.transfer.Transmitter#verifyTarget(org.alfresco.service.cmr.transfer.TransferTarget)
- */
- public void verifyTarget(TransferTarget target) throws TransferException
- {
- HttpMethod verifyRequest = getPostMethod();
- try
- {
- HostConfiguration hostConfig = getHostConfig(target);
- HttpState httpState = getHttpState(target);
-
- verifyRequest.setPath(target.getEndpointPath() + "/test");
- try
- {
- int response = httpClient.executeMethod(hostConfig, verifyRequest, httpState);
- checkResponseStatus("verifyTarget", response, verifyRequest);
- }
- catch (RuntimeException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- String error = "Failed to execute HTTP request to target";
- log.debug(error, e);
- throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"verifyTraget", target.toString(), e.toString()}, e);
- }
- }
- finally
- {
- verifyRequest.releaseConnection();
- }
- }
-
- /**
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.transfer.Transmitter#verifyTarget(org.alfresco.service.cmr.transfer.TransferTarget)
+ */
+ public void verifyTarget(TransferTarget target) throws TransferException
+ {
+ HttpMethod verifyRequest = getPostMethod();
+ try
+ {
+ HostConfiguration hostConfig = getHostConfig(target);
+ HttpState httpState = getHttpState(target);
+
+ verifyRequest.setPath(target.getEndpointPath() + "/test");
+ try
+ {
+ int response = httpClient.executeMethod(hostConfig, verifyRequest, httpState);
+ checkResponseStatus("verifyTarget", response, verifyRequest);
+ }
+ catch (RuntimeException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ String error = "Failed to execute HTTP request to target";
+ log.debug(error, e);
+ throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"verifyTraget", target.toString(), e.toString()}, e);
+ }
+ }
+ finally
+ {
+ verifyRequest.releaseConnection();
+ }
+ }
+
+ /**
*
* @param methodName String
* @param response int
* @param method HttpMethod
- */
- private void checkResponseStatus(String methodName, int response, HttpMethod method)
- {
- if (response != 200)
- {
- Throwable error = null;
- try
- {
- log.error("Received \"unsuccessful\" response code from target server: " + response);
- String errorPayload = method.getResponseBodyAsString();
- JSONObject errorObj = new JSONObject(errorPayload);
- error = rehydrateError(errorObj);
- }
- catch (Exception ex)
- {
- throw new TransferException(MSG_UNSUCCESSFUL_RESPONSE, new Object[] {methodName, response});
- }
- if ((error != null) && TransferException.class.isAssignableFrom(error.getClass()))
- {
- throw (TransferException)error;
- }
- else
- {
- throw new TransferException(MSG_UNSUCCESSFUL_RESPONSE, new Object[] {methodName, response});
- }
- }
- }
-
- /**
- * Get the HTTPState for a transfer target
+ */
+ private void checkResponseStatus(String methodName, int response, HttpMethod method)
+ {
+ if (response != 200)
+ {
+ Throwable error = null;
+ try
+ {
+ log.error("Received \"unsuccessful\" response code from target server: " + response);
+ String errorPayload = method.getResponseBodyAsString();
+ JSONObject errorObj = new JSONObject(errorPayload);
+ error = rehydrateError(errorObj);
+ }
+ catch (Exception ex)
+ {
+ throw new TransferException(MSG_UNSUCCESSFUL_RESPONSE, new Object[] {methodName, response});
+ }
+ if ((error != null) && TransferException.class.isAssignableFrom(error.getClass()))
+ {
+ throw (TransferException)error;
+ }
+ else
+ {
+ throw new TransferException(MSG_UNSUCCESSFUL_RESPONSE, new Object[] {methodName, response});
+ }
+ }
+ }
+
+ /**
+ * Get the HTTPState for a transfer target
* @param target TransferTarget
* @return HttpState
- */
- protected HttpState getHttpState(TransferTarget target)
- {
- HttpState httpState = new HttpState();
- httpState.setCredentials(new AuthScope(target.getEndpointHost(), target.getEndpointPort(),
- AuthScope.ANY_REALM),
- new UsernamePasswordCredentials(target.getUsername(), new String(target.getPassword())));
- return httpState;
- }
-
- /**
+ */
+ private HttpState getHttpState(TransferTarget target)
+ {
+ HttpState httpState = new HttpState();
+ httpState.setCredentials(new AuthScope(target.getEndpointHost(), target.getEndpointPort(),
+ AuthScope.ANY_REALM),
+ new UsernamePasswordCredentials(target.getUsername(), new String(target.getPassword())));
+
+ String requiredProtocol = target.getEndpointProtocol();
+ if (requiredProtocol == null)
+ {
+ throw new TransferException(MSG_UNSUPPORTED_PROTOCOL, new Object[] {requiredProtocol});
+ }
+
+ Protocol protocol = protocolMap.get(requiredProtocol.toLowerCase().trim());
+ if (protocol == null)
+ {
+ log.error("Unsupported protocol: " + requiredProtocol);
+ throw new TransferException(MSG_UNSUPPORTED_PROTOCOL, new Object[] {requiredProtocol});
+ }
+
+ // Use the appropriate Proxy credentials if required
+ if (httpProxyHost != null && HTTP_SCHEME_NAME.equals(protocol.getScheme()) && HttpClientHelper.requiresProxy(target.getEndpointHost()))
+ {
+ if (httpProxyCredentials != null)
+ {
+ httpState.setProxyCredentials(httpAuthScope, httpProxyCredentials);
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("Using HTTP proxy credentials for proxy: " + httpProxyHost.getHostName());
+ }
+ }
+ }
+ else if (httpsProxyHost != null && HTTPS_SCHEME_NAME.equals(protocol.getScheme()) && HttpClientHelper.requiresProxy(target.getEndpointHost()))
+ {
+ if (httpsProxyCredentials != null)
+ {
+ httpState.setProxyCredentials(httpsAuthScope, httpsProxyCredentials);
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("Using HTTPS proxy credentials for proxy: " + httpsProxyHost.getHostName());
+ }
+ }
+ }
+
+ return httpState;
+ }
+
+ /**
* @param target TransferTarget
* @return HostConfiguration
- */
- private HostConfiguration getHostConfig(TransferTarget target)
- {
- String requiredProtocol = target.getEndpointProtocol();
- if (requiredProtocol == null)
- {
- throw new TransferException(MSG_UNSUPPORTED_PROTOCOL, new Object[] {target.getEndpointProtocol()});
- }
-
- Protocol protocol = protocolMap.get(requiredProtocol.toLowerCase().trim());
- if (protocol == null) {
- log.error("Unsupported protocol: " + target.getEndpointProtocol());
- throw new TransferException(MSG_UNSUPPORTED_PROTOCOL, new Object[] {target.getEndpointProtocol()});
- }
-
- HostConfiguration hostConfig = new HostConfiguration();
- hostConfig.setHost(target.getEndpointHost(), target.getEndpointPort(), protocol);
- return hostConfig;
- }
-
- public Transfer begin(TransferTarget target, String fromRepositoryId, TransferVersion fromVersion) throws TransferException
- {
- PostMethod beginRequest = getPostMethod();
- try
- {
- HostConfiguration hostConfig = getHostConfig(target);
- HttpState httpState = getHttpState(target);
-
- beginRequest.setPath(target.getEndpointPath() + "/begin");
- try
- {
- NameValuePair[] nameValuePair = new NameValuePair[] {
- new NameValuePair(TransferCommons.PARAM_FROM_REPOSITORYID, fromRepositoryId),
- new NameValuePair(TransferCommons.PARAM_ALLOW_TRANSFER_TO_SELF, "false"),
- new NameValuePair(TransferCommons.PARAM_VERSION_EDITION, fromVersion.getEdition()),
- new NameValuePair(TransferCommons.PARAM_VERSION_MAJOR, fromVersion.getVersionMajor()),
- new NameValuePair(TransferCommons.PARAM_VERSION_MINOR, fromVersion.getVersionMinor()),
- new NameValuePair(TransferCommons.PARAM_VERSION_REVISION, fromVersion.getVersionRevision())
- };
-
- //add the parameter defining the root of the transfer on the file system if exist
- NodeRef transferRootNode = this.getFileTransferRootNodeRef(target.getNodeRef());
- if (transferRootNode != null)
- {
- //add the parameter
- ArrayList nameValuePairArrayList= new ArrayList(nameValuePair.length + 1);
- Collections.addAll(nameValuePairArrayList,nameValuePair);
- nameValuePairArrayList.add(new NameValuePair(TransferCommons.PARAM_ROOT_FILE_TRANSFER, transferRootNode.toString()));
- nameValuePair = nameValuePairArrayList.toArray(new NameValuePair[0]);
- }
-
- beginRequest.setRequestBody(nameValuePair);
-
- int responseStatus = httpClient.executeMethod(hostConfig, beginRequest, httpState);
-
- checkResponseStatus("begin", responseStatus, beginRequest);
- //If we get here then we've received a 200 response
- //We're expecting the transfer id encoded in a JSON object...
- JSONObject response = new JSONObject(beginRequest.getResponseBodyAsString());
-
- Transfer transfer = new Transfer();
- transfer.setTransferTarget(target);
-
- String transferId = response.getString(TransferCommons.PARAM_TRANSFER_ID);
- transfer.setTransferId(transferId);
-
- if(response.has(TransferCommons.PARAM_VERSION_MAJOR))
- {
- String versionMajor = response.getString(TransferCommons.PARAM_VERSION_MAJOR);
- String versionMinor = response.getString(TransferCommons.PARAM_VERSION_MINOR);
- String versionRevision = response.getString(TransferCommons.PARAM_VERSION_REVISION);
- String edition = response.getString(TransferCommons.PARAM_VERSION_EDITION);
- TransferVersion version = new TransferVersionImpl(versionMajor, versionMinor, versionRevision, edition);
- transfer.setToVersion(version);
- }
- else
- {
- TransferVersion version = new TransferVersionImpl("0", "0", "0", "Unknown");
- transfer.setToVersion(version);
- }
-
- if(log.isDebugEnabled())
- {
- log.debug("begin transfer transferId:" + transferId +", target:" + target);
- }
-
- return transfer;
- }
- catch (RuntimeException e)
- {
- log.debug("unexpected exception", e);
- throw e;
- }
- catch (Exception e)
- {
- String error = "Failed to execute HTTP request to target";
- log.debug(error, e);
- throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[] {"begin", target.toString(), e.toString()}, e);
- }
- }
- finally
- {
- log.debug("releasing connection");
- beginRequest.releaseConnection();
- }
- }
-
- public void sendManifest(Transfer transfer, File manifest, OutputStream result) throws TransferException
- {
- TransferTarget target = transfer.getTransferTarget();
- PostMethod postSnapshotRequest = getPostMethod();
- MultipartRequestEntity requestEntity;
-
- if(log.isDebugEnabled())
- {
- log.debug("does manifest exist? " + manifest.exists());
- log.debug("sendManifest file : " + manifest.getAbsoluteFile());
- }
-
-
- try
- {
- HostConfiguration hostConfig = getHostConfig(target);
- HttpState httpState = getHttpState(target);
-
- try
- {
- postSnapshotRequest.setPath(target.getEndpointPath() + "/post-snapshot");
-
- //Put the transferId on the query string
- postSnapshotRequest.setQueryString(
- new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
-
- //TODO encapsulate the name of the manifest part
- //And add the manifest file as a "part"
- Part file = new FilePart(TransferCommons.PART_NAME_MANIFEST, manifest);
- requestEntity = new MultipartRequestEntity(new Part[] {file}, postSnapshotRequest.getParams());
- postSnapshotRequest.setRequestEntity(requestEntity);
-
- int responseStatus = httpClient.executeMethod(hostConfig, postSnapshotRequest, httpState);
- checkResponseStatus("sendManifest", responseStatus, postSnapshotRequest);
-
- InputStream is = postSnapshotRequest.getResponseBodyAsStream();
-
- final ReadableByteChannel inputChannel = Channels.newChannel(is);
- final WritableByteChannel outputChannel = Channels.newChannel(result);
- try
- {
- // copy the channels
- channelCopy(inputChannel, outputChannel);
- }
- finally
- {
- inputChannel.close();
- outputChannel.close();
- }
-
- return;
- }
- catch (RuntimeException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- String error = "Failed to execute HTTP request to target";
- log.debug(error, e);
- throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"sendManifest", target.toString(), e.toString()}, e);
- }
- }
- finally
- {
- postSnapshotRequest.releaseConnection();
- }
- }
-
- public void abort(Transfer transfer) throws TransferException
- {
- TransferTarget target = transfer.getTransferTarget();
- HttpMethod abortRequest = getPostMethod();
- try
- {
- HostConfiguration hostConfig = getHostConfig(target);
- HttpState httpState = getHttpState(target);
-
- abortRequest.setPath(target.getEndpointPath() + "/abort");
- //Put the transferId on the query string
- abortRequest.setQueryString(
- new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
-
- try
- {
- int responseStatus = httpClient.executeMethod(hostConfig, abortRequest, httpState);
- checkResponseStatus("abort", responseStatus, abortRequest);
- //If we get here then we've received a 200 response
- //We're expecting the transfer id encoded in a JSON object...
- }
- catch (RuntimeException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- String error = "Failed to execute HTTP request to target";
- log.debug(error, e);
- throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"abort", target.toString(), e.toString()}, e);
- }
- }
- finally
- {
- abortRequest.releaseConnection();
- }
- }
-
- public void commit(Transfer transfer) throws TransferException
- {
- TransferTarget target = transfer.getTransferTarget();
- HttpMethod commitRequest = getPostMethod();
- try
- {
- HostConfiguration hostConfig = getHostConfig(target);
- HttpState httpState = getHttpState(target);
-
- commitRequest.setPath(target.getEndpointPath() + "/commit");
- //Put the transferId on the query string
- commitRequest.setQueryString(
- new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
- try
- {
- int responseStatus = httpClient.executeMethod(hostConfig, commitRequest, httpState);
- checkResponseStatus("commit", responseStatus, commitRequest);
- //If we get here then we've received a 200 response
- //We're expecting the transfer id encoded in a JSON object...
- }
- catch (RuntimeException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- String error = "Failed to execute HTTP request to target";
- log.error(error, e);
- throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"commit", target.toString(), e.toString()}, e);
- }
- }
- finally
- {
- commitRequest.releaseConnection();
- }
- }
-
- public void prepare(Transfer transfer) throws TransferException
- {
- TransferTarget target = transfer.getTransferTarget();
- HttpMethod prepareRequest = getPostMethod();
- try
- {
- HostConfiguration hostConfig = getHostConfig(target);
- HttpState httpState = getHttpState(target);
-
- prepareRequest.setPath(target.getEndpointPath() + "/prepare");
- //Put the transferId on the query string
- prepareRequest.setQueryString(
- new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
- try
- {
- int responseStatus = httpClient.executeMethod(hostConfig, prepareRequest, httpState);
- checkResponseStatus("prepare", responseStatus, prepareRequest);
- //If we get here then we've received a 200 response
- //We're expecting the transfer id encoded in a JSON object...
- }
- catch (RuntimeException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- String error = "Failed to execute HTTP request to target";
- log.debug(error, e);
- throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"prepare", target.toString(), e.toString()}, e);
- }
- }
- finally
- {
- prepareRequest.releaseConnection();
- }
- }
-
- /**
- *
- */
- public void sendContent(Transfer transfer, Set data) throws TransferException
- {
- if(log.isDebugEnabled())
- {
- log.debug("send content to transfer:" + transfer);
- }
-
- TransferTarget target = transfer.getTransferTarget();
- PostMethod postContentRequest = getPostMethod();
-
- try
- {
- HostConfiguration hostConfig = getHostConfig(target);
- HttpState httpState = getHttpState(target);
-
- try
- {
- postContentRequest.setPath(target.getEndpointPath() + "/post-content");
- //Put the transferId on the query string
- postContentRequest.setQueryString(
- new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
-
- //Put the transferId on the query string
- postContentRequest.setQueryString(
- new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
-
- Part[] parts = new Part[data.size()];
-
- int index = 0;
- for(ContentData content : data)
- {
- String contentUrl = content.getContentUrl();
- String fileName = TransferCommons.URLToPartName(contentUrl);
- log.debug("content partName: " + fileName);
-
- parts[index++] = new ContentDataPart(getContentService(), fileName, content);
- }
-
- MultipartRequestEntity requestEntity = new MultipartRequestEntity(parts, postContentRequest.getParams());
- postContentRequest.setRequestEntity(requestEntity);
-
- int responseStatus = httpClient.executeMethod(hostConfig, postContentRequest, httpState);
- checkResponseStatus("sendContent", responseStatus, postContentRequest);
-
- if(log.isDebugEnabled())
- {
- log.debug("sent content");
- }
-
- }
- catch (RuntimeException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- String error = "Failed to execute HTTP request to target";
- log.debug(error, e);
- throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"sendContent", target.toString(), e.toString()}, e);
- }
- }
- finally
- {
- postContentRequest.releaseConnection();
- }
- } // end of sendContent
-
- /**
- *
- */
- public TransferProgress getStatus(Transfer transfer) throws TransferException
- {
- TransferTarget target = transfer.getTransferTarget();
- HttpMethod statusRequest = getPostMethod();
- try
- {
- HostConfiguration hostConfig = getHostConfig(target);
- HttpState httpState = getHttpState(target);
-
- statusRequest.setPath(target.getEndpointPath() + "/status");
- //Put the transferId on the query string
- statusRequest.setQueryString(
- new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
-
- try
- {
- int responseStatus = httpClient.executeMethod(hostConfig, statusRequest, httpState);
- checkResponseStatus("status", responseStatus, statusRequest);
- //If we get here then we've received a 200 response
- String statusPayload = statusRequest.getResponseBodyAsString();
- JSONObject statusObj = new JSONObject(statusPayload);
- //We're expecting the transfer progress encoded in a JSON object...
- int currentPosition = statusObj.getInt("currentPosition");
- int endPosition = statusObj.getInt("endPosition");
- String statusStr= statusObj.getString("status");
-
- TransferProgress p = new TransferProgress();
-
- if(statusObj.has("error"))
- {
- JSONObject errorJSON = statusObj.getJSONObject("error");
- Throwable throwable = rehydrateError(errorJSON);
- p.setError(throwable);
- }
-
- p.setStatus(TransferProgress.Status.valueOf(statusStr));
- p.setCurrentPosition(currentPosition);
- p.setEndPosition(endPosition);
-
- return p;
- }
- catch (RuntimeException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- String error = "Failed to execute HTTP request to target";
- log.debug(error, e);
- throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"status", target.toString(), e.toString()}, e);
- }
- }
- finally
- {
- statusRequest.releaseConnection();
- }
- }
-
- /**
- *
- */
- public void getTransferReport(Transfer transfer, OutputStream result)
- {
- TransferTarget target = transfer.getTransferTarget();
- PostMethod getReportRequest = getPostMethod();
- try
- {
- HostConfiguration hostConfig = getHostConfig(target);
- HttpState httpState = getHttpState(target);
-
- try
- {
- getReportRequest.setPath(target.getEndpointPath() + "/report");
-
- //Put the transferId on the query string
- getReportRequest.setQueryString(
- new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
-
- int responseStatus = httpClient.executeMethod(hostConfig, getReportRequest, httpState);
- checkResponseStatus("getReport", responseStatus, getReportRequest);
-
- InputStream is = getReportRequest.getResponseBodyAsStream();
-
- // Now copy the response input stream to result.
- final ReadableByteChannel inputChannel = Channels.newChannel(is);
- final WritableByteChannel outputChannel = Channels.newChannel(result);
- try
- {
- // copy the channels
- channelCopy(inputChannel, outputChannel);
- }
- finally
- {
- // closing the channels
- inputChannel.close();
- outputChannel.close();
- }
-
- return;
- }
- catch (RuntimeException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- String error = "Failed to execute HTTP request to target";
- log.debug(error, e);
- throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"getTransferReport", target.toString(), e.toString()}, e);
- }
- }
- finally
- {
- getReportRequest.releaseConnection();
- }
- }
-
- private static void channelCopy(final ReadableByteChannel src, final WritableByteChannel dest) throws IOException
- {
- final ByteBuffer buffer = ByteBuffer.allocateDirect(2 * 1024);
- while (src.read(buffer) != -1)
- {
- // prepare the buffer to be drained
- buffer.flip();
- // write to the channel, may block
- dest.write(buffer);
-
- // If partial transfer, shift remainder down
- // If buffer is empty, same as doing clear()
- buffer.compact();
- }
-
- // EOF will leave buffer in fill state
- buffer.flip();
-
- // make sure the buffer is fully drained.
- while (buffer.hasRemaining())
- {
- dest.write(buffer);
- }
- }
-
- protected PostMethod getPostMethod()
- {
- return httpMethodFactory.createPostMethod();
- }
-
- /**
- *
- * @param errorJSON A JSON object expected to hold the name of the error class ("errorType"),
- * the error message ("errorMessage"), and, optionally, the Alfresco message id ("alfrescoErrorId")
- * and Alfresco message parameters ("alfrescoErrorParams").
- * @return The rehydrated error object, or null if errorJSON is null.
+ */
+ private HostConfiguration getHostConfig(TransferTarget target)
+ {
+ String requiredProtocol = target.getEndpointProtocol();
+ if (requiredProtocol == null)
+ {
+ throw new TransferException(MSG_UNSUPPORTED_PROTOCOL, new Object[] {requiredProtocol});
+ }
+
+ Protocol protocol = protocolMap.get(requiredProtocol.toLowerCase().trim());
+ if (protocol == null)
+ {
+ log.error("Unsupported protocol: " + target.getEndpointProtocol());
+ throw new TransferException(MSG_UNSUPPORTED_PROTOCOL, new Object[] {requiredProtocol});
+ }
+
+ HostConfiguration hostConfig = new HostConfiguration();
+ hostConfig.setHost(target.getEndpointHost(), target.getEndpointPort(), protocol);
+
+ // Use the appropriate Proxy Host if required
+ if (httpProxyHost != null && HTTP_SCHEME_NAME.equals(protocol.getScheme()) && HttpClientHelper.requiresProxy(target.getEndpointHost()))
+ {
+ hostConfig.setProxyHost(httpProxyHost);
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("Using HTTP proxy host for: " + target.getEndpointHost());
+ }
+ }
+ else if (httpsProxyHost != null && HTTPS_SCHEME_NAME.equals(protocol.getScheme()) && HttpClientHelper.requiresProxy(target.getEndpointHost()))
+ {
+ hostConfig.setProxyHost(httpsProxyHost);
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("Using HTTPS proxy host for: " + target.getEndpointHost());
+ }
+ }
+ return hostConfig;
+ }
+
+ /**
+ * Create suitable AuthScope for ProxyHost. If the ProxyHost is null, no AuthsScope will be created.
+ * @param proxyHost ProxyHost
+ * @return AuthScope for provided ProxyHost, null otherwise.
+ */
+ private AuthScope createProxyAuthScope(final ProxyHost proxyHost)
+ {
+ AuthScope authScope = null;
+ if (proxyHost != null)
+ {
+ authScope = new AuthScope(proxyHost.getHostName(), proxyHost.getPort());
+ }
+ return authScope;
+ }
+
+ public Transfer begin(TransferTarget target, String fromRepositoryId, TransferVersion fromVersion) throws TransferException
+ {
+ PostMethod beginRequest = getPostMethod();
+ try
+ {
+ HostConfiguration hostConfig = getHostConfig(target);
+ HttpState httpState = getHttpState(target);
+
+ beginRequest.setPath(target.getEndpointPath() + "/begin");
+ try
+ {
+ NameValuePair[] nameValuePair = new NameValuePair[] {
+ new NameValuePair(TransferCommons.PARAM_FROM_REPOSITORYID, fromRepositoryId),
+ new NameValuePair(TransferCommons.PARAM_ALLOW_TRANSFER_TO_SELF, "false"),
+ new NameValuePair(TransferCommons.PARAM_VERSION_EDITION, fromVersion.getEdition()),
+ new NameValuePair(TransferCommons.PARAM_VERSION_MAJOR, fromVersion.getVersionMajor()),
+ new NameValuePair(TransferCommons.PARAM_VERSION_MINOR, fromVersion.getVersionMinor()),
+ new NameValuePair(TransferCommons.PARAM_VERSION_REVISION, fromVersion.getVersionRevision())
+ };
+
+ //add the parameter defining the root of the transfer on the file system if exist
+ NodeRef transferRootNode = this.getFileTransferRootNodeRef(target.getNodeRef());
+ if (transferRootNode != null)
+ {
+ //add the parameter
+ ArrayList nameValuePairArrayList= new ArrayList(nameValuePair.length + 1);
+ Collections.addAll(nameValuePairArrayList,nameValuePair);
+ nameValuePairArrayList.add(new NameValuePair(TransferCommons.PARAM_ROOT_FILE_TRANSFER, transferRootNode.toString()));
+ nameValuePair = nameValuePairArrayList.toArray(new NameValuePair[0]);
+ }
+
+ beginRequest.setRequestBody(nameValuePair);
+
+ int responseStatus = httpClient.executeMethod(hostConfig, beginRequest, httpState);
+
+ checkResponseStatus("begin", responseStatus, beginRequest);
+ //If we get here then we've received a 200 response
+ //We're expecting the transfer id encoded in a JSON object...
+ JSONObject response = new JSONObject(beginRequest.getResponseBodyAsString());
+
+ Transfer transfer = new Transfer();
+ transfer.setTransferTarget(target);
+
+ String transferId = response.getString(TransferCommons.PARAM_TRANSFER_ID);
+ transfer.setTransferId(transferId);
+
+ if(response.has(TransferCommons.PARAM_VERSION_MAJOR))
+ {
+ String versionMajor = response.getString(TransferCommons.PARAM_VERSION_MAJOR);
+ String versionMinor = response.getString(TransferCommons.PARAM_VERSION_MINOR);
+ String versionRevision = response.getString(TransferCommons.PARAM_VERSION_REVISION);
+ String edition = response.getString(TransferCommons.PARAM_VERSION_EDITION);
+ TransferVersion version = new TransferVersionImpl(versionMajor, versionMinor, versionRevision, edition);
+ transfer.setToVersion(version);
+ }
+ else
+ {
+ TransferVersion version = new TransferVersionImpl("0", "0", "0", "Unknown");
+ transfer.setToVersion(version);
+ }
+
+ if(log.isDebugEnabled())
+ {
+ log.debug("begin transfer transferId:" + transferId +", target:" + target);
+ }
+
+ return transfer;
+ }
+ catch (RuntimeException e)
+ {
+ log.debug("unexpected exception", e);
+ throw e;
+ }
+ catch (Exception e)
+ {
+ String error = "Failed to execute HTTP request to target";
+ log.debug(error, e);
+ throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[] {"begin", target.toString(), e.toString()}, e);
+ }
+ }
+ finally
+ {
+ log.debug("releasing connection");
+ beginRequest.releaseConnection();
+ }
+ }
+
+ public void sendManifest(Transfer transfer, File manifest, OutputStream result) throws TransferException
+ {
+ TransferTarget target = transfer.getTransferTarget();
+ PostMethod postSnapshotRequest = getPostMethod();
+ MultipartRequestEntity requestEntity;
+
+ if(log.isDebugEnabled())
+ {
+ log.debug("does manifest exist? " + manifest.exists());
+ log.debug("sendManifest file : " + manifest.getAbsoluteFile());
+ }
+
+
+ try
+ {
+ HostConfiguration hostConfig = getHostConfig(target);
+ HttpState httpState = getHttpState(target);
+
+ try
+ {
+ postSnapshotRequest.setPath(target.getEndpointPath() + "/post-snapshot");
+
+ //Put the transferId on the query string
+ postSnapshotRequest.setQueryString(
+ new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
+
+ //TODO encapsulate the name of the manifest part
+ //And add the manifest file as a "part"
+ Part file = new FilePart(TransferCommons.PART_NAME_MANIFEST, manifest);
+ requestEntity = new MultipartRequestEntity(new Part[] {file}, postSnapshotRequest.getParams());
+ postSnapshotRequest.setRequestEntity(requestEntity);
+
+ int responseStatus = httpClient.executeMethod(hostConfig, postSnapshotRequest, httpState);
+ checkResponseStatus("sendManifest", responseStatus, postSnapshotRequest);
+
+ InputStream is = postSnapshotRequest.getResponseBodyAsStream();
+
+ final ReadableByteChannel inputChannel = Channels.newChannel(is);
+ final WritableByteChannel outputChannel = Channels.newChannel(result);
+ try
+ {
+ // copy the channels
+ channelCopy(inputChannel, outputChannel);
+ }
+ finally
+ {
+ inputChannel.close();
+ outputChannel.close();
+ }
+
+ return;
+ }
+ catch (RuntimeException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ String error = "Failed to execute HTTP request to target";
+ log.debug(error, e);
+ throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"sendManifest", target.toString(), e.toString()}, e);
+ }
+ }
+ finally
+ {
+ postSnapshotRequest.releaseConnection();
+ }
+ }
+
+ public void abort(Transfer transfer) throws TransferException
+ {
+ TransferTarget target = transfer.getTransferTarget();
+ HttpMethod abortRequest = getPostMethod();
+ try
+ {
+ HostConfiguration hostConfig = getHostConfig(target);
+ HttpState httpState = getHttpState(target);
+
+ abortRequest.setPath(target.getEndpointPath() + "/abort");
+ //Put the transferId on the query string
+ abortRequest.setQueryString(
+ new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
+
+ try
+ {
+ int responseStatus = httpClient.executeMethod(hostConfig, abortRequest, httpState);
+ checkResponseStatus("abort", responseStatus, abortRequest);
+ //If we get here then we've received a 200 response
+ //We're expecting the transfer id encoded in a JSON object...
+ }
+ catch (RuntimeException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ String error = "Failed to execute HTTP request to target";
+ log.debug(error, e);
+ throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"abort", target.toString(), e.toString()}, e);
+ }
+ }
+ finally
+ {
+ abortRequest.releaseConnection();
+ }
+ }
+
+ public void commit(Transfer transfer) throws TransferException
+ {
+ TransferTarget target = transfer.getTransferTarget();
+ HttpMethod commitRequest = getPostMethod();
+ try
+ {
+ HostConfiguration hostConfig = getHostConfig(target);
+ HttpState httpState = getHttpState(target);
+
+ commitRequest.setPath(target.getEndpointPath() + "/commit");
+ //Put the transferId on the query string
+ commitRequest.setQueryString(
+ new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
+ try
+ {
+ int responseStatus = httpClient.executeMethod(hostConfig, commitRequest, httpState);
+ checkResponseStatus("commit", responseStatus, commitRequest);
+ //If we get here then we've received a 200 response
+ //We're expecting the transfer id encoded in a JSON object...
+ }
+ catch (RuntimeException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ String error = "Failed to execute HTTP request to target";
+ log.error(error, e);
+ throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"commit", target.toString(), e.toString()}, e);
+ }
+ }
+ finally
+ {
+ commitRequest.releaseConnection();
+ }
+ }
+
+ public void prepare(Transfer transfer) throws TransferException
+ {
+ TransferTarget target = transfer.getTransferTarget();
+ HttpMethod prepareRequest = getPostMethod();
+ try
+ {
+ HostConfiguration hostConfig = getHostConfig(target);
+ HttpState httpState = getHttpState(target);
+
+ prepareRequest.setPath(target.getEndpointPath() + "/prepare");
+ //Put the transferId on the query string
+ prepareRequest.setQueryString(
+ new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
+ try
+ {
+ int responseStatus = httpClient.executeMethod(hostConfig, prepareRequest, httpState);
+ checkResponseStatus("prepare", responseStatus, prepareRequest);
+ //If we get here then we've received a 200 response
+ //We're expecting the transfer id encoded in a JSON object...
+ }
+ catch (RuntimeException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ String error = "Failed to execute HTTP request to target";
+ log.debug(error, e);
+ throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"prepare", target.toString(), e.toString()}, e);
+ }
+ }
+ finally
+ {
+ prepareRequest.releaseConnection();
+ }
+ }
+
+ /**
+ *
+ */
+ public void sendContent(Transfer transfer, Set data) throws TransferException
+ {
+ if(log.isDebugEnabled())
+ {
+ log.debug("send content to transfer:" + transfer);
+ }
+
+ TransferTarget target = transfer.getTransferTarget();
+ PostMethod postContentRequest = getPostMethod();
+
+ try
+ {
+ HostConfiguration hostConfig = getHostConfig(target);
+ HttpState httpState = getHttpState(target);
+
+ try
+ {
+ postContentRequest.setPath(target.getEndpointPath() + "/post-content");
+ //Put the transferId on the query string
+ postContentRequest.setQueryString(
+ new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
+
+ //Put the transferId on the query string
+ postContentRequest.setQueryString(
+ new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
+
+ Part[] parts = new Part[data.size()];
+
+ int index = 0;
+ for(ContentData content : data)
+ {
+ String contentUrl = content.getContentUrl();
+ String fileName = TransferCommons.URLToPartName(contentUrl);
+ log.debug("content partName: " + fileName);
+
+ parts[index++] = new ContentDataPart(getContentService(), fileName, content);
+ }
+
+ MultipartRequestEntity requestEntity = new MultipartRequestEntity(parts, postContentRequest.getParams());
+ postContentRequest.setRequestEntity(requestEntity);
+
+ int responseStatus = httpClient.executeMethod(hostConfig, postContentRequest, httpState);
+ checkResponseStatus("sendContent", responseStatus, postContentRequest);
+
+ if(log.isDebugEnabled())
+ {
+ log.debug("sent content");
+ }
+
+ }
+ catch (RuntimeException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ String error = "Failed to execute HTTP request to target";
+ log.debug(error, e);
+ throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"sendContent", target.toString(), e.toString()}, e);
+ }
+ }
+ finally
+ {
+ postContentRequest.releaseConnection();
+ }
+ } // end of sendContent
+
+ /**
+ *
+ */
+ public TransferProgress getStatus(Transfer transfer) throws TransferException
+ {
+ TransferTarget target = transfer.getTransferTarget();
+ HttpMethod statusRequest = getPostMethod();
+ try
+ {
+ HostConfiguration hostConfig = getHostConfig(target);
+ HttpState httpState = getHttpState(target);
+
+ statusRequest.setPath(target.getEndpointPath() + "/status");
+ //Put the transferId on the query string
+ statusRequest.setQueryString(
+ new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
+
+ try
+ {
+ int responseStatus = httpClient.executeMethod(hostConfig, statusRequest, httpState);
+ checkResponseStatus("status", responseStatus, statusRequest);
+ //If we get here then we've received a 200 response
+ String statusPayload = statusRequest.getResponseBodyAsString();
+ JSONObject statusObj = new JSONObject(statusPayload);
+ //We're expecting the transfer progress encoded in a JSON object...
+ int currentPosition = statusObj.getInt("currentPosition");
+ int endPosition = statusObj.getInt("endPosition");
+ String statusStr= statusObj.getString("status");
+
+ TransferProgress p = new TransferProgress();
+
+ if(statusObj.has("error"))
+ {
+ JSONObject errorJSON = statusObj.getJSONObject("error");
+ Throwable throwable = rehydrateError(errorJSON);
+ p.setError(throwable);
+ }
+
+ p.setStatus(TransferProgress.Status.valueOf(statusStr));
+ p.setCurrentPosition(currentPosition);
+ p.setEndPosition(endPosition);
+
+ return p;
+ }
+ catch (RuntimeException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ String error = "Failed to execute HTTP request to target";
+ log.debug(error, e);
+ throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"status", target.toString(), e.toString()}, e);
+ }
+ }
+ finally
+ {
+ statusRequest.releaseConnection();
+ }
+ }
+
+ /**
+ *
+ */
+ public void getTransferReport(Transfer transfer, OutputStream result)
+ {
+ TransferTarget target = transfer.getTransferTarget();
+ PostMethod getReportRequest = getPostMethod();
+ try
+ {
+ HostConfiguration hostConfig = getHostConfig(target);
+ HttpState httpState = getHttpState(target);
+
+ try
+ {
+ getReportRequest.setPath(target.getEndpointPath() + "/report");
+
+ //Put the transferId on the query string
+ getReportRequest.setQueryString(
+ new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
+
+ int responseStatus = httpClient.executeMethod(hostConfig, getReportRequest, httpState);
+ checkResponseStatus("getReport", responseStatus, getReportRequest);
+
+ InputStream is = getReportRequest.getResponseBodyAsStream();
+
+ // Now copy the response input stream to result.
+ final ReadableByteChannel inputChannel = Channels.newChannel(is);
+ final WritableByteChannel outputChannel = Channels.newChannel(result);
+ try
+ {
+ // copy the channels
+ channelCopy(inputChannel, outputChannel);
+ }
+ finally
+ {
+ // closing the channels
+ inputChannel.close();
+ outputChannel.close();
+ }
+
+ return;
+ }
+ catch (RuntimeException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ String error = "Failed to execute HTTP request to target";
+ log.debug(error, e);
+ throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"getTransferReport", target.toString(), e.toString()}, e);
+ }
+ }
+ finally
+ {
+ getReportRequest.releaseConnection();
+ }
+ }
+
+ private static void channelCopy(final ReadableByteChannel src, final WritableByteChannel dest) throws IOException
+ {
+ final ByteBuffer buffer = ByteBuffer.allocateDirect(2 * 1024);
+ while (src.read(buffer) != -1)
+ {
+ // prepare the buffer to be drained
+ buffer.flip();
+ // write to the channel, may block
+ dest.write(buffer);
+
+ // If partial transfer, shift remainder down
+ // If buffer is empty, same as doing clear()
+ buffer.compact();
+ }
+
+ // EOF will leave buffer in fill state
+ buffer.flip();
+
+ // make sure the buffer is fully drained.
+ while (buffer.hasRemaining())
+ {
+ dest.write(buffer);
+ }
+ }
+
+ protected PostMethod getPostMethod()
+ {
+ return httpMethodFactory.createPostMethod();
+ }
+
+ /**
+ *
+ * @param errorJSON A JSON object expected to hold the name of the error class ("errorType"),
+ * the error message ("errorMessage"), and, optionally, the Alfresco message id ("alfrescoErrorId")
+ * and Alfresco message parameters ("alfrescoErrorParams").
+ * @return The rehydrated error object, or null if errorJSON is null.
* Throws {@code JSONException} if an error occurs while parsing the supplied JSON object
- */
- private Throwable rehydrateError(JSONObject errorJSON)
- {
- return jsonErrorSerializer.deserialize(errorJSON);
- }
-
- public void setContentService(ContentService contentService)
- {
- this.contentService = contentService;
- }
-
- public ContentService getContentService()
- {
- return contentService;
- }
-
- public void setHttpMethodFactory(HttpMethodFactory httpMethodFactory)
- {
- this.httpMethodFactory = httpMethodFactory;
- }
-
- public void setJsonErrorSerializer(JsonSerializer jsonErrorSerializer)
- {
- this.jsonErrorSerializer = jsonErrorSerializer;
- }
-
- public void setNodeService(NodeService nodeService)
- {
- this.nodeService = nodeService;
- }
-
- private NodeRef getFileTransferRootNodeRef(NodeRef transferNodeRef)
- {
- //testing if transferring to file system
- if(!TransferModel.TYPE_FILE_TRANSFER_TARGET.equals(nodeService.getType(transferNodeRef)))
- return null;
-
- //get association
- List assocs = nodeService.getTargetAssocs(transferNodeRef, TransferModel.ASSOC_ROOT_FILE_TRANSFER);
- if(assocs.size() == 0 || assocs.size() > 1)
- return null;
-
- return assocs.get(0).getTargetRef();
- }
-
-
-}
+ */
+ private Throwable rehydrateError(JSONObject errorJSON)
+ {
+ return jsonErrorSerializer.deserialize(errorJSON);
+ }
+
+ public void setContentService(ContentService contentService)
+ {
+ this.contentService = contentService;
+ }
+
+ public ContentService getContentService()
+ {
+ return contentService;
+ }
+
+ public void setHttpMethodFactory(HttpMethodFactory httpMethodFactory)
+ {
+ this.httpMethodFactory = httpMethodFactory;
+ }
+
+ public void setJsonErrorSerializer(JsonSerializer jsonErrorSerializer)
+ {
+ this.jsonErrorSerializer = jsonErrorSerializer;
+ }
+
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ private NodeRef getFileTransferRootNodeRef(NodeRef transferNodeRef)
+ {
+ //testing if transferring to file system
+ if(!TransferModel.TYPE_FILE_TRANSFER_TARGET.equals(nodeService.getType(transferNodeRef)))
+ return null;
+
+ //get association
+ List assocs = nodeService.getTargetAssocs(transferNodeRef, TransferModel.ASSOC_ROOT_FILE_TRANSFER);
+ if(assocs.size() == 0 || assocs.size() > 1)
+ return null;
+
+ return assocs.get(0).getTargetRef();
+ }
+
+
+}
diff --git a/source/java/org/alfresco/util/HttpClientHelper.java b/source/java/org/alfresco/util/HttpClientHelper.java
index 885395658e..47a3da69b9 100644
--- a/source/java/org/alfresco/util/HttpClientHelper.java
+++ b/source/java/org/alfresco/util/HttpClientHelper.java
@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
- * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -25,10 +25,16 @@
*/
package org.alfresco.util;
-import org.alfresco.httpclient.HttpClientFactory;
-import org.apache.commons.httpclient.HttpClient;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import java.util.StringTokenizer;
+
+import org.alfresco.httpclient.HttpClientFactory;
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.ProxyHost;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.webscripts.connector.RemoteClient;
/**
@@ -39,7 +45,20 @@ import org.springframework.extensions.webscripts.connector.RemoteClient;
* otherwise things will break for the next request in this thread!
*
* TODO Merge me back to Spring Surf, which is where this code has been
- * pulled out from (was in {@link RemoteClient} but not available externally)
+ * pulled out from (was in {@link RemoteClient} but not available externally)
+ *
+ * This class also provides support for creating proxy configurations,
+ * taking into account System properties like:
+ *
+ *
+ * - http.proxyHost
+ * - http.proxyPort
+ * - http.nonProxyHosts
+ * - http.proxyUser
+ * - http.proxyPassword
+ *
+ *
+ *
*/
public class HttpClientHelper
{
@@ -63,5 +82,84 @@ public class HttpClientHelper
public static HttpClient getHttpClient()
{
return httpClient.get();
+ }
+
+ /**
+ * Create proxy host for the given system host and port properties.
+ * If the properties are not set, no proxy will be created.
+ *
+ * @param hostProperty the name of the system property for the proxy server (http.proxyHost
or https.proxyHost
)
+ * @param portProperty the name of the system property for the proxy server port (http.proxyPort)
+ * @param defaultPort
+ *
+ * @return ProxyHost if appropriate properties have been set, null otherwise
+ */
+ public static ProxyHost createProxyHost(final String hostProperty, final String portProperty, final int defaultPort)
+ {
+ final String proxyHost = System.getProperty(hostProperty);
+ ProxyHost proxy = null;
+ if (proxyHost != null && proxyHost.length() != 0)
+ {
+ final String strProxyPort = System.getProperty(portProperty);
+ if (strProxyPort == null || strProxyPort.length() == 0)
+ {
+ proxy = new ProxyHost(proxyHost, defaultPort);
+ }
+ else
+ {
+ proxy = new ProxyHost(proxyHost, Integer.parseInt(strProxyPort));
+ }
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("ProxyHost: " + proxy.toString());
+ }
+ }
+ return proxy;
+ }
+
+ /**
+ * Create the proxy credentials for the given proxy user and password properties.
+ * If the properties are not set, not credentials will be created.
+ * @param proxyUserProperty the name of the system property for the proxy user
+ * @param proxyPasswordProperty the name of the system property for the proxy password
+ * @return Credentials if appropriate properties have been set, null otherwise
+ */
+ public static Credentials createProxyCredentials(final String proxyUserProperty, final String proxyPasswordProperty)
+ {
+ final String proxyUser = System.getProperty(proxyUserProperty);
+ final String proxyPassword = System.getProperty(proxyPasswordProperty);
+ Credentials credentials = null;
+ if (StringUtils.isNotBlank(proxyUser))
+ {
+ credentials = new UsernamePasswordCredentials(proxyUser, proxyPassword);
+ }
+ return credentials;
+ }
+
+ /**
+ * Return true unless the given target host is specified in the http.nonProxyHosts
system property.
+ * See http://docs.oracle.com/javase/8/docs/api/java/net/doc-files/net-properties.html
+ * @param targetHost Non-null host name to verify
+ * @return true if not specified in the list, false if it is specified and therefore should be excluded from proxy
+ */
+ public static boolean requiresProxy(final String targetHost)
+ {
+ boolean requiresProxy = true;
+ final String nonProxyHosts = System.getProperty("http.nonProxyHosts");
+ if (nonProxyHosts != null)
+ {
+ StringTokenizer tokenizer = new StringTokenizer(nonProxyHosts, "|");
+ while (tokenizer.hasMoreTokens())
+ {
+ String pattern = tokenizer.nextToken();
+ pattern = pattern.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*");
+ if (targetHost.matches(pattern))
+ {
+ requiresProxy = false;
+ break;
+ }
+ }
+ }
+ return requiresProxy;
}
}