493014: [Proxy] Eclipse Neon 4.6 error trying to access Marketplace using proxy.

Allow disabling transports via property.

Also, disable Apache HttpClient transport if it is disabled via ECF
property -Dorg.eclipse.ecf.provider.filetransfer.excludeContributors=
org.eclipse.ecf.provider.filetransfer.httpclient4

Bug: 493014
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=493014
diff --git a/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/util/FallbackTransportFactory.java b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/util/FallbackTransportFactory.java
index 2af3b9a..1534b60 100644
--- a/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/util/FallbackTransportFactory.java
+++ b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/util/FallbackTransportFactory.java
@@ -146,8 +146,9 @@
 		if (delegateFactory == null) {
 			BundleContext bundleContext = FrameworkUtil.getBundle(getClass()).getBundleContext();
 			try {
-				Collection<ServiceReference<ITransportFactory>> serviceReferences = bundleContext
-						.getServiceReferences(ITransportFactory.class, null);
+				String disabledTransportsFilter = TransportFactory.computeDisabledTransportsFilter();
+				Collection<ServiceReference<ITransportFactory>> serviceReferences = bundleContext.getServiceReferences(
+						ITransportFactory.class, "".equals(disabledTransportsFilter) ? null : disabledTransportsFilter); //$NON-NLS-1$
 				if (!serviceReferences.isEmpty()) {
 					for (ServiceReference<ITransportFactory> serviceReference : serviceReferences) {
 						ITransportFactory service = bundleContext.getService(serviceReference);
diff --git a/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/util/TransportFactory.java b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/util/TransportFactory.java
index de29ed4..347a733 100644
--- a/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/util/TransportFactory.java
+++ b/org.eclipse.epp.mpc.core/src/org/eclipse/epp/internal/mpc/core/util/TransportFactory.java
@@ -18,8 +18,10 @@
 import java.util.ArrayList;

 import java.util.Collection;

 import java.util.HashMap;

+import java.util.HashSet;

 import java.util.List;

 import java.util.Map;

+import java.util.Set;

 

 import org.apache.http.NoHttpResponseException;

 import org.eclipse.core.runtime.CoreException;

@@ -32,6 +34,7 @@
 import org.eclipse.epp.mpc.core.service.ITransportFactory;

 import org.eclipse.epp.mpc.core.service.ServiceHelper;

 import org.osgi.framework.BundleContext;

+import org.osgi.framework.FrameworkUtil;

 import org.osgi.framework.InvalidSyntaxException;

 import org.osgi.framework.ServiceReference;

 import org.osgi.service.component.ComponentConstants;

@@ -52,11 +55,49 @@
 

 	public static final String LEGACY_TRANSPORT_COMPONENT_NAME = "org.eclipse.epp.mpc.core.transportfactory.legacy"; //$NON-NLS-1$

 

+	public static final String DISABLED_TRANSPORTS_KEY = "org.eclipse.epp.mpc.core.service.transport.disabled"; //$NON-NLS-1$

+

 	private static final String[] factoryClasses = new String[] { //

 			"org.eclipse.epp.internal.mpc.core.util.P2TransportFactory", // //$NON-NLS-1$

 			"org.eclipse.epp.internal.mpc.core.util.Eclipse36TransportFactory", // //$NON-NLS-1$

 	"org.eclipse.epp.internal.mpc.core.util.JavaPlatformTransportFactory" }; //$NON-NLS-1$

 

+	private static final String HTTP_TRANSPORT_FACTORY_ID = "org.eclipse.epp.mpc.core.transport.http.factory"; //$NON-NLS-1$

+

+	private static final String HTTP_TRANSPORT_WRAPPER_ID = "org.eclipse.epp.mpc.core.transport.http.wrapper"; //$NON-NLS-1$

+

+	private static final String ECF_HTTPCLIENT4_TRANSPORT_ID = "org.eclipse.ecf.provider.filetransfer.httpclient4"; //$NON-NLS-1$

+

+	private static final String ECF_EXCLUDES_PROPERTY = "org.eclipse.ecf.provider.filetransfer.excludeContributors"; //$NON-NLS-1$

+

+	public static String computeDisabledTransportsFilter() {

+		BundleContext bundleContext = FrameworkUtil.getBundle(TransportFactory.class).getBundleContext();

+		String disabledTransportsStr = bundleContext.getProperty(DISABLED_TRANSPORTS_KEY);

+		if (disabledTransportsStr == null) {

+			disabledTransportsStr = ""; //$NON-NLS-1$

+		}

+		String excludeContributors = bundleContext

+				.getProperty(ECF_EXCLUDES_PROPERTY);

+		if (excludeContributors != null && excludeContributors.contains(ECF_HTTPCLIENT4_TRANSPORT_ID)) {

+			disabledTransportsStr += "," + HTTP_TRANSPORT_WRAPPER_ID + "," + HTTP_TRANSPORT_FACTORY_ID; //$NON-NLS-1$//$NON-NLS-2$

+		}

+		Set<String> disabledTransports = new HashSet<String>();

+		StringBuilder bldr = new StringBuilder("(&"); //$NON-NLS-1$

+		for (String transportName : disabledTransportsStr.split(",")) { //$NON-NLS-1$

+			transportName = transportName.trim();

+			if (!"".equals(transportName) && disabledTransports.add(transportName)) { //$NON-NLS-1$

+				bldr.append("(!(") //$NON-NLS-1$

+				.append(ComponentConstants.COMPONENT_NAME)

+				.append("=") //$NON-NLS-1$

+				.append(transportName)

+				.append("))"); //$NON-NLS-1$

+			}

+		}

+		bldr.append(")"); //$NON-NLS-1$

+		String disabledTransportsFilter = disabledTransports.isEmpty() ? "" : bldr.toString(); //$NON-NLS-1$

+		return disabledTransportsFilter;

+	}

+

 	public static final class LegacyFactory implements ITransportFactory {

 		private ITransportFactory delegate;

 

@@ -77,9 +118,11 @@
 			BundleContext bundleContext = context.getBundleContext();

 			Collection<ServiceReference<ITransportFactory>> serviceReferences = bundleContext.getServiceReferences(

 					ITransportFactory.class,

-					"(&(" + LEGACY_TRANSPORT_KEY + "=true)" //$NON-NLS-1$//$NON-NLS-2$

-					+ "(!(" + ComponentConstants.COMPONENT_NAME + "=" + LEGACY_TRANSPORT_COMPONENT_NAME //$NON-NLS-1$//$NON-NLS-2$

-					+ ")))"); //$NON-NLS-1$

+					"(&" //$NON-NLS-1$

+					+ "(" + LEGACY_TRANSPORT_KEY + "=true)" //$NON-NLS-1$//$NON-NLS-2$

+					+ "(!(" + ComponentConstants.COMPONENT_NAME + "=" + LEGACY_TRANSPORT_COMPONENT_NAME + "))" //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$

+					+ computeDisabledTransportsFilter()

+					+ ")"); //$NON-NLS-1$

 			if (!serviceReferences.isEmpty()) {

 				for (ServiceReference<ITransportFactory> serviceReference : serviceReferences) {

 					ITransportFactory service = bundleContext.getService(serviceReference);

@@ -174,13 +217,14 @@
 	public static org.eclipse.epp.mpc.core.service.ITransport createTransport() {

 		//search for registered factory service

 		BundleContext context = MarketplaceClientCorePlugin.getBundle().getBundleContext();

-		ServiceReference<ITransportFactory> serviceReference = context.getServiceReference(ITransportFactory.class);

+		ServiceReference<ITransportFactory> serviceReference = getTransportServiceReference(context);

 		if (serviceReference != null) {

 			ITransportFactory transportService = context.getService(serviceReference);

 			if (transportService != null) {

 				try {

 					return transportService.getTransport();

 				} finally {

+					transportService = null;

 					context.ungetService(serviceReference);

 				}

 			}

@@ -188,6 +232,26 @@
 		throw new IllegalStateException();

 	}

 

+	public static ServiceReference<ITransportFactory> getTransportServiceReference(BundleContext context) {

+		ServiceReference<ITransportFactory> serviceReference = null;

+		String disabledTransportsFilter = computeDisabledTransportsFilter();

+		if ("".equals(disabledTransportsFilter)) { //$NON-NLS-1$

+			serviceReference = context.getServiceReference(ITransportFactory.class);

+		} else {

+			try {

+				Collection<ServiceReference<ITransportFactory>> serviceReferences = context

+						.getServiceReferences(ITransportFactory.class, disabledTransportsFilter);

+				if (!serviceReferences.isEmpty()) {

+					serviceReference = serviceReferences.iterator().next();

+				}

+			} catch (InvalidSyntaxException e) {

+				MarketplaceClientCore.error(e);

+				serviceReference = context.getServiceReference(ITransportFactory.class);

+			}

+		}

+		return serviceReference;

+	}

+

 	public static List<ITransportFactory> listAvailableFactories() {

 		List<ITransportFactory> factories = new ArrayList<ITransportFactory>();

 		for (String factoryClass : factoryClasses) {

diff --git a/org.eclipse.epp.mpc.tests/META-INF/MANIFEST.MF b/org.eclipse.epp.mpc.tests/META-INF/MANIFEST.MF
index 12f5c54..b4aec1f 100644
--- a/org.eclipse.epp.mpc.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.epp.mpc.tests/META-INF/MANIFEST.MF
@@ -31,6 +31,8 @@
 Import-Package: org.eclipse.ecf.core;version="3.0.0",
  org.eclipse.ecf.core.util,
  org.eclipse.ecf.filetransfer,
+ org.eclipse.ecf.internal.provider.filetransfer,
+ org.eclipse.ecf.internal.provider.filetransfer.httpclient4,
  org.eclipse.equinox.security.storage;version="1.0.0",
  org.osgi.service.component
 Export-Package: org.eclipse.epp.mpc.tests;x-internal:=true,
diff --git a/org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/util/TransportFactoryTest.java b/org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/util/TransportFactoryTest.java
index 443cbaa..739f9b2 100644
--- a/org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/util/TransportFactoryTest.java
+++ b/org.eclipse.epp.mpc.tests/src/org/eclipse/epp/mpc/tests/util/TransportFactoryTest.java
@@ -43,6 +43,7 @@
 import org.eclipse.epp.mpc.core.service.ServiceHelper;
 import org.eclipse.epp.mpc.core.service.ServiceUnavailableException;
 import org.hamcrest.CoreMatchers;
+import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Matchers;
 import org.mockito.Mockito;
@@ -53,6 +54,12 @@
 
 public class TransportFactoryTest {
 
+	@Before
+	public void clearTransportFilters() {
+		System.getProperties().remove("org.eclipse.epp.mpc.core.service.transport.disabled");
+		System.getProperties().remove("org.eclipse.ecf.provider.filetransfer.excludeContributors");
+	}
+
 	@Test
 	public void testRegisteredFactories() throws Exception {
 		BundleContext context = MarketplaceClientCorePlugin.getBundle().getBundleContext();
@@ -138,6 +145,30 @@
 		assertEquals("org.eclipse.epp.mpc.core.transport.http.wrapper", transportServiceName);
 	}
 
+	@Test
+	public void testDisableTransports() {
+		System.setProperty("org.eclipse.epp.mpc.core.service.transport.disabled",
+				"org.eclipse.epp.mpc.core.transport.http.wrapper");
+		String transportServiceName = getTransportServiceName();
+		assertEquals("legacy:org.eclipse.epp.internal.mpc.core.util.P2TransportFactory", transportServiceName);
+
+		System.setProperty("org.eclipse.epp.mpc.core.service.transport.disabled",
+				"org.eclipse.epp.mpc.core.transport.http.wrapper,"
+						+ "legacy:org.eclipse.epp.internal.mpc.core.util.P2TransportFactory,"
+						+ "legacy:org.eclipse.epp.internal.mpc.core.util.Eclipse36TransportFactory");
+		transportServiceName = getTransportServiceName();
+		assertEquals("legacy:org.eclipse.epp.internal.mpc.core.util.JavaPlatformTransportFactory",
+				transportServiceName);
+	}
+
+	@Test
+	public void testDisableHttpClientTransportsThroughECF() {
+		System.setProperty("org.eclipse.ecf.provider.filetransfer.excludeContributors",
+				"org.eclipse.ecf.provider.filetransfer.httpclient4");
+		String transportServiceName = getTransportServiceName();
+		assertEquals("legacy:org.eclipse.epp.internal.mpc.core.util.P2TransportFactory", transportServiceName);
+	}
+
 	@Test(expected = ServiceUnavailableException.class)
 	public void testHttpClientTransportErrorHandling() throws Exception {
 		createFailingHttpClientTransport().stream(URI.create("http://127.0.0.1:54321"), null);
@@ -186,6 +217,14 @@
 		assertSame(expectedResultStream, stream);
 	}
 
+	@Test
+	public void testECFContributorPropertiesUnchanged() {
+		assertEquals("org.eclipse.ecf.provider.filetransfer.excludeContributors",
+				org.eclipse.ecf.internal.provider.filetransfer.Activator.PLUGIN_EXCLUDED_SYS_PROP_NAME);
+		assertEquals("org.eclipse.ecf.provider.filetransfer.httpclient4",
+				org.eclipse.ecf.internal.provider.filetransfer.httpclient4.Activator.PLUGIN_ID);
+	}
+
 	private static HttpResponse mockResponse(StatusLine statusLine, HttpEntity entity) {
 		HttpResponse mockResponse = Mockito.mock(HttpResponse.class);
 		Mockito.when(mockResponse.getStatusLine()).thenReturn(statusLine);
@@ -202,8 +241,8 @@
 
 	private static String getTransportServiceName() {
 		BundleContext bundleContext = FrameworkUtil.getBundle(TransportFactory.class).getBundleContext();
-		ServiceReference<ITransportFactory> transportServiceReference = bundleContext.getServiceReference(
-				ITransportFactory.class);
+		ServiceReference<ITransportFactory> transportServiceReference = TransportFactory.getTransportServiceReference(
+				bundleContext);
 		if (transportServiceReference != null) {
 			String transportServiceName = (String) transportServiceReference.getProperty(
 					ComponentConstants.COMPONENT_NAME);