diff options
author | Mengxin Zhu | 2011-09-02 07:18:09 +0000 |
---|---|---|
committer | Mengxin Zhu | 2011-09-02 08:07:23 +0000 |
commit | df0e3ecefa5df573f6b51a49155442d83fdb2a5f (patch) | |
tree | 726a1f93126212e5816f9b178f17cff618876b6c | |
parent | 8c591f781927fc324e96d166f1af22d125c8372a (diff) | |
download | rt.equinox.p2-df0e3ecefa5df573f6b51a49155442d83fdb2a5f.tar.gz rt.equinox.p2-df0e3ecefa5df573f6b51a49155442d83fdb2a5f.tar.xz rt.equinox.p2-df0e3ecefa5df573f6b51a49155442d83fdb2a5f.zip |
fix 350014 to use a system property to set the retrying number if socketv20110902-0807
timeout happened
Change-Id: I1bab6db693a3ee739e058bda1a4d00fbc8bd1eb8
11 files changed, 362 insertions, 1 deletions
diff --git a/bundles/org.eclipse.equinox.p2.tests/All p2 Tests.launch b/bundles/org.eclipse.equinox.p2.tests/All p2 Tests.launch index e6bb76b06..e28d16008 100644 --- a/bundles/org.eclipse.equinox.p2.tests/All p2 Tests.launch +++ b/bundles/org.eclipse.equinox.p2.tests/All p2 Tests.launch @@ -57,7 +57,7 @@ <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consolelog -console"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.equinox.p2.tests"/> <stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/> -<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dorg.eclipse.equinox.p2.reconciler.tests.platform.archive=c:/dev/platform/zips/eclipse-platform-3.6M6-win32.zip -Dorg.eclipse.equinox.p2.reconciler.tests.35.platform.archive=c:/dev/platform/zips/eclipse-platform-3.5-win32.zip -Dorg.eclipse.equinox.p2.repository -Dorg.eclipse.equinox.p2.tests.current.build.repo=http://eclipsebuildserv/3.6-I-builds/ -Xmx512m"/> +<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dorg.eclipse.equinox.p2.reconciler.tests.platform.archive=c:/dev/platform/zips/eclipse-platform-3.6M6-win32.zip -Dorg.eclipse.equinox.p2.reconciler.tests.35.platform.archive=c:/dev/platform/zips/eclipse-platform-3.5-win32.zip -Dorg.eclipse.equinox.p2.repository -Dorg.eclipse.equinox.p2.tests.current.build.repo=http://eclipsebuildserv/3.6-I-builds/ -Xmx512m -Dorg.eclipse.ecf.provider.filetransfer.httpclient.browse.connectTimeout=10000 -Dorg.eclipse.ecf.provider.filetransfer.httpclient.retrieve.connectTimeout=10000 -Dorg.eclipse.ecf.provider.filetransfer.httpclient.retrieve.readTimeout=10000"/> <stringAttribute key="pde.version" value="3.3"/> <stringAttribute key="product" value="org.eclipse.sdk.ide"/> <booleanAttribute key="run_in_ui_thread" value="true"/> diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/AllTests.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/AllTests.java index 74095af3b..7dade7be2 100644 --- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/AllTests.java +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/AllTests.java @@ -35,6 +35,7 @@ public class AllTests extends TestCase { suite.addTestSuite(MD5Tests.class); suite.addTestSuite(MirrorSelectorTest.class); suite.addTestSuite(MirrorRequestTest.class); + suite.addTestSuite(MirrorRequestTest2.class); suite.addTestSuite(SimpleArtifactRepositoryTest.class); suite.addTestSuite(TransferTest.class); return suite; diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/MirrorRequestTest2.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/MirrorRequestTest2.java new file mode 100644 index 000000000..0c9d67cbe --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/MirrorRequestTest2.java @@ -0,0 +1,157 @@ +package org.eclipse.equinox.p2.tests.artifact.repository; + +import java.io.File; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import org.eclipse.core.runtime.*; +import org.eclipse.equinox.internal.p2.artifact.repository.MirrorRequest; +import org.eclipse.equinox.internal.p2.artifact.repository.MirrorSelector; +import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository; +import org.eclipse.equinox.internal.p2.metadata.ArtifactKey; +import org.eclipse.equinox.internal.p2.repository.Transport; +import org.eclipse.equinox.internal.p2.transport.ecf.RepositoryTransport; +import org.eclipse.equinox.p2.core.ProvisionException; +import org.eclipse.equinox.p2.metadata.IArtifactKey; +import org.eclipse.equinox.p2.metadata.Version; +import org.eclipse.equinox.p2.query.*; +import org.eclipse.equinox.p2.repository.IRepository; +import org.eclipse.equinox.p2.repository.artifact.*; +import org.eclipse.equinox.p2.repository.artifact.spi.AbstractArtifactRepository; +import org.eclipse.equinox.p2.tests.AbstractProvisioningTest; +import org.eclipse.equinox.p2.tests.testserver.helper.AbstractTestServerClientCase; + +public class MirrorRequestTest2 extends AbstractTestServerClientCase { + + private SimpleArtifactRepository sourceRepository; + private File targetLocation; + private SimpleArtifactRepository targetRepository; + + @Override + public void setUp() throws Exception { + super.setUp(); + targetLocation = File.createTempFile("target", ".repo"); + targetLocation.delete(); + targetLocation.mkdirs(); + targetRepository = new SimpleArtifactRepository(getAgent(), "TargetRepo", targetLocation.toURI(), null); + + URI location = URI.create(getBaseURL() + "/mirrorrequest"); + + IArtifactRepositoryManager mgr = (IArtifactRepositoryManager) getAgent().getService(IArtifactRepositoryManager.SERVICE_NAME); + sourceRepository = (SimpleArtifactRepository) mgr.loadRepository(location, null); + } + + public void tearDown() throws Exception { + IArtifactRepositoryManager mgr = (IArtifactRepositoryManager) getAgent().getService(IArtifactRepositoryManager.SERVICE_NAME); + mgr.removeRepository(targetLocation.toURI()); + AbstractProvisioningTest.delete(targetLocation); + super.tearDown(); + } + + public void testRetryMirrorAfterTimeout() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { + // call test + IArtifactKey key = new ArtifactKey("test.txt", "HelloWorldText", Version.parseVersion("1.0.0")); + MirrorRequest request = new MirrorRequest(key, targetRepository, null, null, (Transport) getAgent().getService(Transport.SERVICE_NAME)); + MirrorRepo mirrorRepo = new MirrorRepo(sourceRepository); + Field field = sourceRepository.getClass().getDeclaredField("mirrors"); + field.setAccessible(true); + field.set(sourceRepository, new MirrorSelector(mirrorRepo, (Transport) getAgent().getService(Transport.SERVICE_NAME)) { + private int count = 0; + + @Override + public synchronized URI getMirrorLocation(URI inputLocation, IProgressMonitor monitor) { + if (count++ == 0) { + return inputLocation; + } + return URI.create(getBaseURL() + "/mirrorrequest/mirror-two/plugins/HelloWorldText_1.0.0.txt"); + } + + @Override + public synchronized boolean hasValidMirror() { + return true; + } + }); + + request.perform(mirrorRepo, new NullProgressMonitor()); + + // The download succeeded + assertTrue(request.getResult().toString(), request.getResult().isOK()); + } + + public void testTimeoutForgivableAfterTimeout() { + try { + System.setProperty(RepositoryTransport.TIMEOUT_RETRY, "4"); + // call test + IArtifactKey key = new ArtifactKey("test.txt", "HelloWorldText", Version.parseVersion("1.0.0")); + MirrorRequest request = new MirrorRequest(key, targetRepository, null, null, (Transport) getAgent().getService(Transport.SERVICE_NAME)); + request.perform(sourceRepository, new NullProgressMonitor()); + + // The download succeeded + assertTrue(request.getResult().toString(), request.getResult().isOK()); + } finally { + System.clearProperty(RepositoryTransport.TIMEOUT_RETRY); + } + } + + protected class MirrorRepo extends AbstractArtifactRepository { + SimpleArtifactRepository delegate; + int downloadCount = 0; + + MirrorRepo(SimpleArtifactRepository repo) { + super(getAgent(), repo.getName(), repo.getType(), repo.getVersion(), repo.getLocation(), repo.getDescription(), repo.getProvider(), repo.getProperties()); + delegate = repo; + } + + @Override + public String getProperty(String key) { + return getProperties().get(key); + } + + @Override + public synchronized Map<String, String> getProperties() { + Map<String, String> newProperties = new HashMap<String, String>(super.getProperties()); + newProperties.put(IRepository.PROP_MIRRORS_URL, getBaseURL() + "/mirrorrequest/mirrors.xml"); + newProperties.put(IRepository.PROP_MIRRORS_BASE_URL, getBaseURL() + "/mirrorrequest"); + return newProperties; + } + + public boolean contains(IArtifactDescriptor descriptor) { + return delegate.contains(descriptor); + } + + public boolean contains(IArtifactKey key) { + return delegate.contains(key); + } + + public IStatus getArtifact(IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) { + downloadCount++; + return delegate.getArtifact(descriptor, destination, monitor); + } + + public IArtifactDescriptor[] getArtifactDescriptors(IArtifactKey key) { + return delegate.getArtifactDescriptors(key); + } + + public IStatus getArtifacts(IArtifactRequest[] requests, IProgressMonitor monitor) { + return delegate.getArtifacts(requests, monitor); + } + + public OutputStream getOutputStream(IArtifactDescriptor descriptor) throws ProvisionException { + return delegate.getOutputStream(descriptor); + } + + public IStatus getRawArtifact(IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) { + return delegate.getRawArtifact(descriptor, destination, monitor); + } + + public IQueryable<IArtifactDescriptor> descriptorQueryable() { + return delegate.descriptorQueryable(); + } + + public IQueryResult<IArtifactKey> query(IQuery<IArtifactKey> query, IProgressMonitor monitor) { + return delegate.query(query, monitor); + } + } +} diff --git a/bundles/org.eclipse.equinox.p2.testserver/src/org/eclipse/equinox/p2/testserver/Activator.java b/bundles/org.eclipse.equinox.p2.testserver/src/org/eclipse/equinox/p2/testserver/Activator.java index 746d63487..90cbd16ac 100644 --- a/bundles/org.eclipse.equinox.p2.testserver/src/org/eclipse/equinox/p2/testserver/Activator.java +++ b/bundles/org.eclipse.equinox.p2.testserver/src/org/eclipse/equinox/p2/testserver/Activator.java @@ -17,6 +17,7 @@ import org.eclipse.equinox.p2.testserver.servlets.BasicResourceDelivery; import org.eclipse.equinox.p2.testserver.servlets.ChopAndDelay; import org.eclipse.equinox.p2.testserver.servlets.ContentLengthLier; import org.eclipse.equinox.p2.testserver.servlets.FileMolester; +import org.eclipse.equinox.p2.testserver.servlets.IntermittentTimeout; import org.eclipse.equinox.p2.testserver.servlets.LastModifiedLier; import org.eclipse.equinox.p2.testserver.servlets.Redirector; import org.eclipse.equinox.p2.testserver.servlets.StatusCodeResponse; @@ -70,9 +71,11 @@ public class Activator implements BundleActivator, ServiceTrackerCustomizer { httpService.registerResources("/private", "/webfiles", secureHttpContext); //$NON-NLS-1$ //$NON-NLS-2$ httpService.registerResources("/never", "/webfiles", alwaysFail); //$NON-NLS-1$ //$NON-NLS-2$ httpService.registerResources("/flipflop", "/webfiles", flipFlop); //$NON-NLS-1$ //$NON-NLS-2$ + // httpService.registerResources("/mirrorrequest", "/webfiles/emptyJarRepo", null); //$NON-NLS-1$ //$NON-NLS-2$ httpService.registerServlet("/status", new StatusCodeResponse(), null, null); //$NON-NLS-1$ httpService.registerServlet("/timeout", new TimeOut(), null, null); //$NON-NLS-1$ + httpService.registerServlet("/mirrorrequest", new IntermittentTimeout("/mirrorrequest", URI.create("http://localhost:" + System.getProperty("org.osgi.service.http.port", "8080") + "/public/emptyJarRepo")), null, null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ httpService.registerServlet("/redirect", new Redirector(), null, null); //$NON-NLS-1$ httpService.registerServlet("/truncated", new Truncator("/truncated", URI.create("/webfiles"), 50), null, null); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ diff --git a/bundles/org.eclipse.equinox.p2.testserver/src/org/eclipse/equinox/p2/testserver/servlets/IntermittentTimeout.java b/bundles/org.eclipse.equinox.p2.testserver/src/org/eclipse/equinox/p2/testserver/servlets/IntermittentTimeout.java new file mode 100644 index 000000000..ac17e7ad5 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.testserver/src/org/eclipse/equinox/p2/testserver/servlets/IntermittentTimeout.java @@ -0,0 +1,83 @@ +package org.eclipse.equinox.p2.testserver.servlets; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.URI; +import java.net.URLConnection; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.eclipse.equinox.p2.testserver.HttpConstants; + +public class IntermittentTimeout extends BasicResourceDelivery { + + /** + * + */ + private static final long serialVersionUID = 2216234319571297257L; + int count = 1; + + public IntermittentTimeout(String theAlias, URI thePath) { + super(theAlias, thePath); + } + + protected void doDeliver(URLConnection conn, InputStream in, String filename, HttpServletRequest request, HttpServletResponse response) throws IOException { + // set when the resource was modified + addDateHeader(response, HttpConstants.LAST_MODIFIED, getLastModified(conn)); + int statusCode = HttpHeaderToStatus(conn.getHeaderField(0)); + + response.setStatus(statusCode != -1 ? HttpServletResponse.SC_OK : statusCode); + + int contentlength = getContentLength(conn); + if (contentlength >= 0) { + response.setContentLength(contentlength); + + String mimeType = computeMimeType(filename, conn); + response.setContentType(mimeType); + + // We want to use a writer if we are sending text + if (mimeType.startsWith("text/")) //$NON-NLS-1$ + { + PrintWriter writer = response.getWriter(); + + writer.flush(); /* write the headers and unbuffer the output */ + + doDelay(filename, 150); + + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + + char buffer[] = new char[4096]; + int read; + while ((read = reader.read(buffer, 0, buffer.length)) != -1) { + writer.write(buffer, 0, read); + } + } else { + ServletOutputStream out = response.getOutputStream(); + + out.flush(); /* write the headers and unbuffer the output */ + + doDelay(filename, 150); + + byte buffer[] = new byte[4096]; + int read; + while ((read = in.read(buffer, 0, buffer.length)) != -1) { + out.write(buffer, 0, read); + out.flush(); + } + } + } + } + + private void doDelay(String filename, int seconds) { + if (filename.endsWith("emptyJarRepo/plugins/HelloWorldText_1.0.0.txt") && (count++ % 3 != 0)) {//$NON-NLS-1$ + try { + Thread.sleep(1000 * seconds); + } catch (InterruptedException e) { + // ignore + } + } + } +} diff --git a/bundles/org.eclipse.equinox.p2.testserver/webfiles/emptyJarRepo/artifacts.xml b/bundles/org.eclipse.equinox.p2.testserver/webfiles/emptyJarRepo/artifacts.xml new file mode 100644 index 000000000..914362402 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.testserver/webfiles/emptyJarRepo/artifacts.xml @@ -0,0 +1,52 @@ +<?xml version='1.0' encoding='UTF-8'?> +<?artifactRepository class='org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository' version='1.0.0'?> +<repository name='HelloWorld Artifacts' type='org.eclipse.equinox.p2.artifact.repository.simpleRepository' version='1.0.0'> + <properties size='5'> + <property name='publishPackFilesAsSiblings' value='true'/> + <property name='p2.compressed' value='false'/> + <property name='p2.timestamp' value='1222368069078'/> + <property name='eclipse.p2.force.threading' value='true'/> + <property name='p2.mirrorsURL' value='mirrors.xml'/> + </properties> + <mappings size='6'> + <rule filter='(& (classifier=osgi.bundle) (format=packed))' output='${repoUrl}/plugins/${id}_${version}.jar.pack.gz'/> + <rule filter='(& (classifier=osgi.bundle))' output='${repoUrl}/plugins/${id}_${version}.jar'/> + <rule filter='(& (classifier=binary))' output='${repoUrl}/binary/${id}_${version}'/> + <rule filter='(& (classifier=org.eclipse.update.feature))' output='${repoUrl}/features/${id}_${version}.jar'/> + <rule filter='(& (classifier=test.txt) (format=packed))' output='${repoUrl}/plugins/${id}_${version}.txt.pack.gz'/> + <rule filter='(& (classifier=test.txt))' output='${repoUrl}/plugins/${id}_${version}.txt'/> + </mappings> + <artifacts size='4'> + <artifact classifier='org.eclipse.update.feature' id='HelloWorldFeature' version='1.0.0'> + <properties size='2'> + <property name='artifact.size' value='0'/> + <property name='download.size' value='0'/> + </properties> + </artifact> + <artifact classifier='test.txt' id='HelloWorldText' version='1.0.0'> + <properties size='3'> + <property name='artifact.size' value='12'/> + <property name='download.size' value='12'/> + <property name='download.md5' value='ed076287532e86365e841e92bfc50d8c'/> + </properties> + </artifact> + <artifact classifier='test.txt' id='fail_to_canonical' version='1.0.0'> + <properties size='3'> + <property name='artifact.size' value='12'/> + <property name='download.size' value='12'/> + <property name='download.md5' value='ed076287532e86365e841e92bfc50d8c'/> + </properties> + </artifact> + <artifact classifier='test.txt' id='fail_to_canonical' version='1.0.0'> + <processing size='1'> + <step id='org.eclipse.equinox.p2.processing.Pack200Unpacker' required='true'/> + </processing> + <properties size='4'> + <property name='artifact.size' value='12'/> + <property name='download.size' value='12'/> + <property name='download.md5' value='ed076287532e86365e841e92bfc50d8c'/> + <property name='format' value='packed'/> + </properties> + </artifact> + </artifacts> +</repository>
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.testserver/webfiles/emptyJarRepo/mirror-two/plugins/HelloWorldText_1.0.0.txt b/bundles/org.eclipse.equinox.p2.testserver/webfiles/emptyJarRepo/mirror-two/plugins/HelloWorldText_1.0.0.txt new file mode 100644 index 000000000..c57eff55e --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.testserver/webfiles/emptyJarRepo/mirror-two/plugins/HelloWorldText_1.0.0.txt @@ -0,0 +1 @@ +Hello World!
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.testserver/webfiles/emptyJarRepo/mirrors.xml b/bundles/org.eclipse.equinox.p2.testserver/webfiles/emptyJarRepo/mirrors.xml new file mode 100644 index 000000000..9faec8f17 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.testserver/webfiles/emptyJarRepo/mirrors.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<mirrors> + <mirror url="mirror-one" label="MirrorOne" /> + <mirror url="mirror-two" label="MirrorTwo" /> +</mirrors>
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.testserver/webfiles/emptyJarRepo/plugins/HelloWorldText_1.0.0.txt b/bundles/org.eclipse.equinox.p2.testserver/webfiles/emptyJarRepo/plugins/HelloWorldText_1.0.0.txt new file mode 100644 index 000000000..c57eff55e --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.testserver/webfiles/emptyJarRepo/plugins/HelloWorldText_1.0.0.txt @@ -0,0 +1 @@ +Hello World!
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.testserver/webfiles/emptyJarRepo/readme.txt b/bundles/org.eclipse.equinox.p2.testserver/webfiles/emptyJarRepo/readme.txt new file mode 100644 index 000000000..133499d32 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.testserver/webfiles/emptyJarRepo/readme.txt @@ -0,0 +1,12 @@ + +Artifact: test.txt,HelloWorldText,1.0.0 + Used by MirrorRequestTest2#testRetryMirrorAfterTimeout() + Mirror one: missing file + Mirror two: get it + Main: intermittent timeout + +Artifact: test.txt,HelloWorldText,1.0.0 + Used by MirrorRequestTest2#testTimeoutForgivableAfterTimeout() + Mirror one: missing file + Mirror two: won't use + Main: intermittent timeout
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.transport.ecf/src/org/eclipse/equinox/internal/p2/transport/ecf/RepositoryTransport.java b/bundles/org.eclipse.equinox.p2.transport.ecf/src/org/eclipse/equinox/internal/p2/transport/ecf/RepositoryTransport.java index bef589f0f..cf433090c 100644 --- a/bundles/org.eclipse.equinox.p2.transport.ecf/src/org/eclipse/equinox/internal/p2/transport/ecf/RepositoryTransport.java +++ b/bundles/org.eclipse.equinox.p2.transport.ecf/src/org/eclipse/equinox/internal/p2/transport/ecf/RepositoryTransport.java @@ -16,8 +16,12 @@ import java.io.FileNotFoundException; import java.io.InputStream; import java.io.OutputStream; import java.net.ConnectException; +import java.net.SocketException; +import java.net.SocketTimeoutException; import java.net.URI; import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.Map; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; @@ -44,6 +48,7 @@ import org.eclipse.equinox.p2.core.IProvisioningAgent; import org.eclipse.equinox.p2.core.ProvisionException; import org.eclipse.equinox.p2.core.UIServices.AuthenticationInfo; import org.eclipse.equinox.p2.core.spi.IAgentServiceFactory; +import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository; import org.eclipse.osgi.util.NLS; /** @@ -54,6 +59,8 @@ import org.eclipse.osgi.util.NLS; public class RepositoryTransport extends Transport implements IAgentServiceFactory { private static RepositoryTransport instance; + public static final String TIMEOUT_RETRY = "org.eclipse.equinox.p2.transport.ecf.retry"; //$NON-NLS-1$ + private static Map<URI, Integer> socketExceptionRetry = null; /** * Returns an shared instance of Generic Transport */ @@ -226,12 +233,51 @@ public class RepositoryTransport extends Transport implements IAgentServiceFacto throw new AuthenticationFailedException(); } + private static boolean isForgiveableException(Throwable t) { + if (t instanceof SocketTimeoutException) + return true; + else if (t instanceof SocketException) + return true; + return false; + } + public static DownloadStatus forStatus(IStatus original, URI toDownload) { Throwable t = original.getException(); + if (isForgiveableException(t) && original.getCode() == IArtifactRepository.CODE_RETRY) + return new DownloadStatus(original.getSeverity(), Activator.ID, original.getCode(), original.getMessage(), t); return forException(t, toDownload); } public static DownloadStatus forException(Throwable t, URI toDownload) { + if (isForgiveableException(t)) { + String value = System.getProperty(TIMEOUT_RETRY); + if (value != null) { + try { + int retry = Integer.valueOf(value).intValue(); + if (retry > 0) { + Integer retryCount = null; + if (socketExceptionRetry == null) { + socketExceptionRetry = new HashMap<URI, Integer>(); + retryCount = new Integer(1); + } else { + Integer alreadyRetryCount = socketExceptionRetry.get(toDownload); + if (alreadyRetryCount == null) + retryCount = new Integer(1); + else if (alreadyRetryCount.intValue() < retry) { + retryCount = new Integer(alreadyRetryCount.intValue() + 1); + } + } + if (retryCount != null) { + socketExceptionRetry.put(toDownload, retryCount); + return new DownloadStatus(IStatus.ERROR, Activator.ID, IArtifactRepository.CODE_RETRY, + NLS.bind(Messages.connection_to_0_failed_on_1_retry_attempt_2, new String[] {toDownload.toString(), t.getMessage(), retryCount.toString()}), t); + } + } + } catch (NumberFormatException e) { + // ignore + } + } + } if (t instanceof FileNotFoundException || (t instanceof IncomingFileTransferException && ((IncomingFileTransferException) t).getErrorCode() == 404)) return new DownloadStatus(IStatus.ERROR, Activator.ID, ProvisionException.ARTIFACT_NOT_FOUND, NLS.bind(Messages.artifact_not_found, toDownload), t); if (t instanceof ConnectException) |