Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoribull2010-02-04 23:58:40 +0000
committeribull2010-02-04 23:58:40 +0000
commit9ca2c2a2a099f684074bbd83ffe0558ff5e56f64 (patch)
treef3103f43b46f6384c43e93c39529c0a610d78740 /bundles
parent2476ddbea1cf40a85520fb9168aa59e2d68b48f2 (diff)
downloadrt.equinox.p2-9ca2c2a2a099f684074bbd83ffe0558ff5e56f64.tar.gz
rt.equinox.p2-9ca2c2a2a099f684074bbd83ffe0558ff5e56f64.tar.xz
rt.equinox.p2-9ca2c2a2a099f684074bbd83ffe0558ff5e56f64.zip
bug 274025: [publisher] p2 metadata generator does not scale
https://bugs.eclipse.org/bugs/show_bug.cgi?id=274025 This adds a batch process to ArtifactRepository which, in the simple artifact repository, will do the save at the end. The publisher is configured to use the batch process now.
Diffstat (limited to 'bundles')
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/CompositeArtifactRepository.java43
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java45
-rw-r--r--bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/CachingArtifactRepository.java10
-rw-r--r--bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepository.java9
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/Publisher.java54
-rw-r--r--bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/IArtifactRepository.java13
-rw-r--r--bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/spi/AbstractArtifactRepository.java13
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/AbstractWrappedArtifactRepository.java4
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/AllTests.java1
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/BatchExecuteArtifactRepositoryTest.java523
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/SimpleArtifactRepositoryTest.java5
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/TestArtifactRepository.java9
-rw-r--r--bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/artifact/UpdateSiteArtifactRepository.java4
13 files changed, 709 insertions, 24 deletions
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/CompositeArtifactRepository.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/CompositeArtifactRepository.java
index a8936f302..e1fb37a64 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/CompositeArtifactRepository.java
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/CompositeArtifactRepository.java
@@ -45,6 +45,7 @@ public class CompositeArtifactRepository extends AbstractArtifactRepository impl
// keep a list of the repositories that we have successfully loaded
private List<ChildInfo> loadedRepos = new ArrayList<ChildInfo>();
private IArtifactRepositoryManager manager;
+ private boolean disableSave;
/**
* Create a Composite repository in memory.
@@ -79,7 +80,7 @@ public class CompositeArtifactRepository extends AbstractArtifactRepository impl
return manager;
}
- /*
+ /**
* This is only called by the parser when loading a repository.
*/
CompositeArtifactRepository(IArtifactRepositoryManager manager, CompositeRepositoryState state) {
@@ -89,7 +90,10 @@ public class CompositeArtifactRepository extends AbstractArtifactRepository impl
addChild(state.getChildren()[i], false);
}
- CompositeArtifactRepository(IArtifactRepositoryManager manager, URI location, String repositoryName, Map<String, String> properties) {
+ /**
+ * @noreference This constructor is not intended to be referenced by clients.
+ */
+ protected CompositeArtifactRepository(IArtifactRepositoryManager manager, URI location, String repositoryName, Map<String, String> properties) {
super(repositoryName, REPOSITORY_TYPE, REPOSITORY_VERSION.toString(), location, null, null, properties);
this.manager = manager;
save();
@@ -393,7 +397,15 @@ public class CompositeArtifactRepository extends AbstractArtifactRepository impl
return applicable.toArray(new IArtifactRequest[applicable.size()]);
}
- private void save() {
+ /**
+ * This method is only protected for testing purposes
+ *
+ * @nooverride This method is not intended to be re-implemented or extended by clients.
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ protected void save() {
+ if (disableSave)
+ return;
if (!isModifiable())
return;
boolean compress = "true".equalsIgnoreCase(properties.get(PROP_COMPRESSED)); //$NON-NLS-1$
@@ -551,4 +563,29 @@ public class CompositeArtifactRepository extends AbstractArtifactRepository impl
CompoundQueryable<IArtifactDescriptor> queryable = new CompoundQueryable<IArtifactDescriptor>(repos);
return queryable;
}
+
+ public IStatus executeBatch(Runnable runnable) {
+ IStatus result = null;
+ synchronized (this) {
+ try {
+ disableSave = true;
+ runnable.run();
+ } catch (Throwable e) {
+ result = new Status(IStatus.ERROR, Activator.ID, e.getMessage(), e);
+ } finally {
+ disableSave = false;
+ try {
+ save();
+ } catch (Exception e) {
+ if (result != null)
+ result = new MultiStatus(Activator.ID, IStatus.ERROR, new IStatus[] {result}, e.getMessage(), e);
+ else
+ result = new Status(IStatus.ERROR, Activator.ID, e.getMessage(), e);
+ }
+ }
+ }
+ if (result == null)
+ result = Status.OK_STATUS;
+ return result;
+ }
}
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java
index 127c7851b..4f9a0c33c 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java
@@ -216,6 +216,8 @@ public class SimpleArtifactRepository extends AbstractArtifactRepository impleme
private MirrorSelector mirrors;
+ private boolean disableSave = false;
+
static void delete(File toDelete) {
if (toDelete.isDirectory()) {
File[] children = toDelete.listFiles();
@@ -437,11 +439,13 @@ public class SimpleArtifactRepository extends AbstractArtifactRepository impleme
simple = createInternalDescriptor(descriptor);
if (simple.getRepositoryProperty(SimpleArtifactDescriptor.ARTIFACT_REFERENCE) == null) {
File file = getArtifactFile(descriptor);
- if (file == null)
- return false;
- delete(file);
- if (file.exists())
- return false;
+ if (file != null) {
+ // If the file != null remove it, otherwise just remove
+ // the descriptor
+ delete(file);
+ if (file.exists())
+ return false;
+ }
}
boolean result = artifactDescriptors.remove(descriptor);
if (result)
@@ -900,11 +904,13 @@ public class SimpleArtifactRepository extends AbstractArtifactRepository impleme
}
public void save() {
- boolean compress = "true".equalsIgnoreCase(properties.get(PROP_COMPRESSED)); //$NON-NLS-1$
+ if (disableSave)
+ return;
+ boolean compress = "true".equalsIgnoreCase((String) properties.get(PROP_COMPRESSED)); //$NON-NLS-1$
save(compress);
}
- public void save(boolean compress) {
+ private void save(boolean compress) {
assertModifiable();
OutputStream os = null;
try {
@@ -990,4 +996,29 @@ public class SimpleArtifactRepository extends AbstractArtifactRepository impleme
public IQueryResult<IArtifactKey> query(IQuery<IArtifactKey> query, IProgressMonitor monitor) {
return query.perform(artifactMap.keySet().iterator());
}
+
+ public IStatus executeBatch(Runnable runnable) {
+ IStatus result = null;
+ synchronized (this) {
+ try {
+ disableSave = true;
+ runnable.run();
+ } catch (Throwable e) {
+ result = new Status(IStatus.ERROR, Activator.ID, e.getMessage(), e);
+ } finally {
+ disableSave = false;
+ try {
+ save();
+ } catch (Exception e) {
+ if (result != null)
+ result = new MultiStatus(Activator.ID, IStatus.ERROR, new IStatus[] {result}, e.getMessage(), e);
+ else
+ result = new Status(IStatus.ERROR, Activator.ID, e.getMessage(), e);
+ }
+ }
+ }
+ if (result == null)
+ result = Status.OK_STATUS;
+ return result;
+ }
}
diff --git a/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/CachingArtifactRepository.java b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/CachingArtifactRepository.java
index 419339d3e..4dcc17383 100644
--- a/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/CachingArtifactRepository.java
+++ b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/CachingArtifactRepository.java
@@ -257,4 +257,14 @@ public class CachingArtifactRepository implements IArtifactRepository, IFileArti
CompoundQueryable<IArtifactKey> compound = new CompoundQueryable<IArtifactKey>(cached, innerRepo);
return compound.query(query, monitor);
}
+
+ public IStatus executeBatch(Runnable runnable) {
+ try {
+ runnable.run();
+ } catch (Exception e) {
+ return new Status(IStatus.ERROR, Activator.ID, e.getMessage(), e);
+ }
+ return Status.OK_STATUS;
+ }
+
}
diff --git a/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepository.java b/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepository.java
index 6879cff7b..9d3830a88 100644
--- a/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepository.java
+++ b/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepository.java
@@ -239,4 +239,13 @@ public class ExtensionLocationArtifactRepository extends AbstractRepository<IArt
ensureInitialized();
return artifactRepository.query(query, monitor);
}
+
+ public IStatus executeBatch(Runnable runnable) {
+ try {
+ runnable.run();
+ } catch (Exception e) {
+ return new Status(IStatus.ERROR, Activator.ID, e.getMessage(), e);
+ }
+ return Status.OK_STATUS;
+ }
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/Publisher.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/Publisher.java
index 06659d4f0..b722a2671 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/Publisher.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/Publisher.java
@@ -188,6 +188,39 @@ public class Publisher {
this.results = results;
}
+ class ArtifactProcess implements Runnable {
+
+ private final IPublisherAction[] actions;
+ private final IPublisherInfo info;
+ private final IProgressMonitor monitor;
+ private IStatus result = null;
+
+ public ArtifactProcess(IPublisherAction[] actions, IPublisherInfo info, IProgressMonitor monitor) {
+ this.monitor = monitor;
+ this.info = info;
+ this.actions = actions;
+ }
+
+ public void run() {
+ MultiStatus finalStatus = new MultiStatus("this", 0, "publishing result", null); //$NON-NLS-1$//$NON-NLS-2$
+ for (int i = 0; i < actions.length; i++) {
+ if (monitor.isCanceled()) {
+ result = Status.CANCEL_STATUS;
+ return;
+ }
+ IStatus status = actions[i].perform(info, results, monitor);
+ finalStatus.merge(status);
+ monitor.worked(1);
+ }
+ result = finalStatus;
+ }
+
+ public IStatus getStatus() {
+ return result;
+ }
+
+ }
+
public IStatus publish(IPublisherAction[] actions, IProgressMonitor monitor) {
if (monitor == null)
monitor = new NullProgressMonitor();
@@ -195,15 +228,20 @@ public class Publisher {
if (Tracing.DEBUG_PUBLISHING)
Tracing.debug("Invoking publisher"); //$NON-NLS-1$
try {
- // run all the actions
- MultiStatus finalStatus = new MultiStatus("this", 0, "publishing result", null); //$NON-NLS-1$//$NON-NLS-2$
- for (int i = 0; i < actions.length; i++) {
- if (sub.isCanceled())
- return Status.CANCEL_STATUS;
- IStatus status = actions[i].perform(info, results, monitor);
- finalStatus.merge(status);
- sub.worked(1);
+ ArtifactProcess artifactProcess = new ArtifactProcess(actions, info, sub);
+
+ IStatus finalStatus = null;
+ if (info.getArtifactRepository() != null) {
+ finalStatus = info.getArtifactRepository().executeBatch(artifactProcess);
+ if (finalStatus.isOK())
+ // If the batch process didn't report any errors, then
+ // Use the status from our actions
+ finalStatus = artifactProcess.getStatus();
+ } else {
+ artifactProcess.run();
+ finalStatus = artifactProcess.getStatus();
}
+
if (Tracing.DEBUG_PUBLISHING)
Tracing.debug("Publishing complete. Result=" + finalStatus); //$NON-NLS-1$
if (!finalStatus.isOK())
diff --git a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/IArtifactRepository.java b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/IArtifactRepository.java
index fd442f9c1..85f56ef10 100644
--- a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/IArtifactRepository.java
+++ b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/IArtifactRepository.java
@@ -139,4 +139,17 @@ public interface IArtifactRepository extends IRepository<IArtifactKey> {
*/
public void removeDescriptor(IArtifactKey key);
+ /**
+ * Executes a runnable against this repository. It is up to the repository
+ * implementor to determine what "batch process" means, for example, it may mean
+ * that the repository serialization is deferred until after the runnable completes.
+ *
+ * The runnable should not execute anything in a separate thread.
+ *
+ * @param process The runnable
+ * @return The result of running the runnable. Any exceptions thrown durring
+ * the execution will be returned in the status.
+ */
+ public IStatus executeBatch(Runnable runnable);
+
}
diff --git a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/spi/AbstractArtifactRepository.java b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/spi/AbstractArtifactRepository.java
index fd7bddb67..43f997060 100644
--- a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/spi/AbstractArtifactRepository.java
+++ b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/spi/AbstractArtifactRepository.java
@@ -10,15 +10,15 @@
*******************************************************************************/
package org.eclipse.equinox.p2.repository.artifact.spi;
-import org.eclipse.equinox.p2.repository.spi.AbstractRepository;
-
import java.io.OutputStream;
import java.net.URI;
import java.util.Map;
import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.repository.Activator;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.metadata.IArtifactKey;
import org.eclipse.equinox.p2.repository.artifact.*;
+import org.eclipse.equinox.p2.repository.spi.AbstractRepository;
/**
* The common base class for all artifact repository implementations. Clients must
@@ -86,4 +86,13 @@ public abstract class AbstractArtifactRepository extends AbstractRepository<IArt
public IArtifactDescriptor createArtifactDescriptor(IArtifactKey key) {
return new ArtifactDescriptor(key);
}
+
+ public IStatus executeBatch(Runnable runnable) {
+ try {
+ runnable.run();
+ } catch (Exception e) {
+ return new Status(IStatus.ERROR, Activator.ID, e.getMessage(), e);
+ }
+ return Status.OK_STATUS;
+ }
}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/AbstractWrappedArtifactRepository.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/AbstractWrappedArtifactRepository.java
index 0343fb74b..fe5a64c35 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/AbstractWrappedArtifactRepository.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/AbstractWrappedArtifactRepository.java
@@ -139,4 +139,8 @@ public class AbstractWrappedArtifactRepository implements IArtifactRepository {
public IQueryResult<IArtifactKey> query(IQuery<IArtifactKey> query, IProgressMonitor monitor) {
return delegate.query(query, monitor);
}
+
+ public IStatus executeBatch(Runnable runnable) {
+ return delegate.executeBatch(runnable);
+ }
}
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 9449b099f..8c6cb05a2 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
@@ -23,6 +23,7 @@ public class AllTests extends TestCase {
suite.addTestSuite(ArtifactRepositoryManagerTest.class);
suite.addTestSuite(ArtifactRepositoryMissingSizeData.class);
suite.addTestSuite(ArtifactRepositoryWithReferenceDescriptors.class);
+ suite.addTestSuite(BatchExecuteArtifactRepositoryTest.class);
suite.addTestSuite(Bug252308.class);
suite.addTestSuite(Bug265577.class);
suite.addTestSuite(CompositeArtifactRepositoryTest.class);
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/BatchExecuteArtifactRepositoryTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/BatchExecuteArtifactRepositoryTest.java
new file mode 100644
index 000000000..adf8ba30d
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/BatchExecuteArtifactRepositoryTest.java
@@ -0,0 +1,523 @@
+/*******************************************************************************
+* Copyright (c) 2009 EclipseSource and others. All rights reserved. This
+* program and the accompanying materials are made available under the terms of
+* the Eclipse Public License v1.0 which accompanies this distribution, and is
+* available at http://www.eclipse.org/legal/epl-v10.html
+*
+* Contributors:
+* EclipseSource - initial API and implementation
+******************************************************************************/
+package org.eclipse.equinox.p2.tests.artifact.repository;
+
+import java.io.*;
+import java.lang.reflect.Field;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.equinox.internal.p2.artifact.repository.CompositeArtifactRepository;
+import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactDescriptor;
+import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository;
+import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
+import org.eclipse.equinox.p2.metadata.Version;
+import org.eclipse.equinox.p2.repository.artifact.*;
+import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
+
+/**
+ * This tests Batch Execution for Artifact Repositories
+ */
+public class BatchExecuteArtifactRepositoryTest extends AbstractProvisioningTest {
+
+ //artifact repository to remove on tear down
+ private File repositoryFile = null;
+ private URI repositoryURI = null;
+
+ private IArtifactDescriptor createDescriptor(String classifier, String id, Version version) {
+ return new SimpleArtifactDescriptor(new ArtifactKey(classifier, id, version));
+ }
+
+ /*
+ * This tests that in the normal case, the batch process runs fine
+ */
+ public void testAdd() {
+ try {
+ repositoryFile = getTempFolder();
+ repositoryURI = repositoryFile.toURI();
+ Map properties = new HashMap();
+ final SimpleArtifactRepository repo = (SimpleArtifactRepository) getArtifactRepositoryManager().createRepository(repositoryURI, "My Repo", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
+ final URI artifactXML = new URI(repositoryFile.toURI().toString() + "/artifacts.xml");
+ IStatus status = repo.executeBatch(new Runnable() {
+ public void run() {
+ repo.addDescriptor(createDescriptor("foo", "foo", Version.emptyVersion));
+ try {
+ assertFalse("1.0", fileContainsString(artifactXML, "foo"));
+ } catch (IOException e) {
+ fail("0.99");
+ }
+ }
+ });
+ assertTrue(status.isOK());
+ assertTrue("1.0", fileContainsString(artifactXML, "foo"));
+ assertEquals("2.0", 1, repo.query(new ArtifactKeyQuery("foo", "foo", null), new NullProgressMonitor()).toSet().size());
+ } catch (Exception e) {
+ fail("Test failed", e);
+ }
+ }
+
+ /*
+ * This tests 3 adds
+ */
+ public void testMultiAdd() {
+ try {
+ repositoryFile = getTempFolder();
+ repositoryURI = repositoryFile.toURI();
+ Map properties = new HashMap();
+ final SimpleArtifactRepository repo = (SimpleArtifactRepository) getArtifactRepositoryManager().createRepository(repositoryURI, "My Repo", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
+ final URI artifactXML = new URI(repositoryFile.toURI().toString() + "/artifacts.xml");
+ IStatus status = repo.executeBatch(new Runnable() {
+ public void run() {
+ repo.addDescriptor(createDescriptor("foo", "foo", Version.emptyVersion));
+ repo.addDescriptor(createDescriptor("bar", "bar", Version.emptyVersion));
+ repo.addDescriptor(createDescriptor("baz", "baz", Version.emptyVersion));
+ try {
+ assertFalse("1.0", fileContainsString(artifactXML, "foo"));
+ assertFalse("1.0", fileContainsString(artifactXML, "bar"));
+ assertFalse("1.0", fileContainsString(artifactXML, "baz"));
+ } catch (IOException e) {
+ fail("0.99");
+ }
+ }
+ });
+ assertTrue(status.isOK());
+ assertEquals("1.0", 1, repo.query(new ArtifactKeyQuery("foo", "foo", null), new NullProgressMonitor()).toSet().size());
+ assertEquals("1.1", 1, repo.query(new ArtifactKeyQuery("bar", "bar", null), new NullProgressMonitor()).toSet().size());
+ assertEquals("1.2", 1, repo.query(new ArtifactKeyQuery("baz", "baz", null), new NullProgressMonitor()).toSet().size());
+ assertTrue("2.0", fileContainsString(artifactXML, "foo"));
+ assertTrue("2.1", fileContainsString(artifactXML, "bar"));
+ assertTrue("2.2", fileContainsString(artifactXML, "baz"));
+ } catch (Exception e) {
+ fail("Test failed", e);
+ }
+ }
+
+ /*
+ * This tests multiple adds with an exception thrown. Makes sure that the descriptors are added
+ */
+ public void testMultiAddWithException() {
+ try {
+ repositoryFile = getTempFolder();
+ repositoryURI = repositoryFile.toURI();
+ Map properties = new HashMap();
+ final SimpleArtifactRepository repo = (SimpleArtifactRepository) getArtifactRepositoryManager().createRepository(repositoryURI, "My Repo", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
+ final URI artifactXML = new URI(repositoryFile.toURI().toString() + "/artifacts.xml");
+ IStatus status = repo.executeBatch(new Runnable() {
+ public void run() {
+ repo.addDescriptor(createDescriptor("foo", "foo", Version.emptyVersion));
+ repo.addDescriptor(createDescriptor("bar", "bar", Version.emptyVersion));
+ throw new RuntimeException();
+ }
+ });
+ assertFalse(status.isOK());
+ assertEquals("1.0", 1, repo.query(new ArtifactKeyQuery("foo", "foo", null), new NullProgressMonitor()).toSet().size());
+ assertEquals("1.1", 1, repo.query(new ArtifactKeyQuery("bar", "bar", null), new NullProgressMonitor()).toSet().size());
+ assertTrue("2.0", fileContainsString(artifactXML, "foo"));
+ assertTrue("2.1", fileContainsString(artifactXML, "bar"));
+ } catch (Exception e) {
+ fail("Test failed", e);
+ }
+ }
+
+ /*
+ * This tests multiple adds with an exception thrown. Makes sure that the descriptors are added
+ */
+ public void testAddAndRemove() {
+ try {
+ repositoryFile = getTempFolder();
+ repositoryURI = repositoryFile.toURI();
+ Map properties = new HashMap();
+ final SimpleArtifactRepository repo = (SimpleArtifactRepository) getArtifactRepositoryManager().createRepository(repositoryURI, "My Repo", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
+ final URI artifactXML = new URI(repositoryFile.toURI().toString() + "/artifacts.xml");
+ IStatus status = repo.executeBatch(new Runnable() {
+ public void run() {
+ IArtifactDescriptor foo = createDescriptor("foo", "foo", Version.emptyVersion);
+ repo.addDescriptor(foo);
+ repo.addDescriptor(createDescriptor("bar", "bar", Version.emptyVersion));
+ repo.removeDescriptor(foo);
+ }
+ });
+ assertTrue(status.isOK());
+ assertEquals("1.0", 1, repo.query(new ArtifactKeyQuery("bar", "bar", null), new NullProgressMonitor()).toSet().size());
+ assertEquals("1.1", 0, repo.query(new ArtifactKeyQuery("foo", "foo", null), new NullProgressMonitor()).toSet().size());
+ assertFalse("2.0", fileContainsString(artifactXML, "foo"));
+ assertTrue("2.1", fileContainsString(artifactXML, "bar"));
+ } catch (Exception e) {
+ fail("Test failed", e);
+ }
+ }
+
+ /*
+ * This tests multiple adds with an exception thrown. Makes sure that the descriptors are added
+ */
+ public void testMultiAddAndRemove() {
+ try {
+ repositoryFile = getTempFolder();
+ repositoryURI = repositoryFile.toURI();
+ Map properties = new HashMap();
+ final SimpleArtifactRepository repo = (SimpleArtifactRepository) getArtifactRepositoryManager().createRepository(repositoryURI, "My Repo", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
+ final URI artifactXML = new URI(repositoryFile.toURI().toString() + "/artifacts.xml");
+ IStatus status = repo.executeBatch(new Runnable() {
+ public void run() {
+ repo.addDescriptor(createDescriptor("1", "1", Version.emptyVersion));
+ repo.addDescriptor(createDescriptor("2", "2", Version.emptyVersion));
+ repo.addDescriptor(createDescriptor("3", "3", Version.emptyVersion));
+ IArtifactDescriptor foo = createDescriptor("foo", "foo", Version.emptyVersion);
+ repo.addDescriptor(foo);
+ repo.addDescriptor(createDescriptor("bar", "bar", Version.emptyVersion));
+ repo.removeDescriptor(foo);
+ }
+ });
+ assertTrue(status.isOK());
+ assertEquals("1.0", 4, repo.query(new ArtifactKeyQuery(null, null, null), new NullProgressMonitor()).toSet().size());
+ assertFalse("2.0", fileContainsString(artifactXML, "foo"));
+ } catch (Exception e) {
+ fail("Test failed", e);
+ }
+ }
+
+ boolean fileContainsString(URI location, String string) throws IOException {
+ StringBuffer buffer = new StringBuffer();
+ BufferedReader reader = new BufferedReader(new FileReader(new File(location)));
+ while (reader.ready())
+ buffer.append(reader.readLine());
+ return buffer.toString().contains(string);
+ }
+
+ /*
+ * This tests that in the normal case, the batch process runs fine
+ */
+ public void testBatchProcessingOK() {
+ try {
+ repositoryFile = getTempFolder();
+ repositoryURI = repositoryFile.toURI();
+ Map properties = new HashMap();
+ SimpleArtifactRepository repo = (SimpleArtifactRepository) getArtifactRepositoryManager().createRepository(repositoryURI, "My Repo", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
+ IStatus status = repo.executeBatch(new Runnable() {
+ public void run() {
+ // empty
+ }
+ });
+ assertTrue(status.isOK());
+ } catch (Exception e) {
+ fail("Test failed", e);
+ }
+ }
+
+ class FailingSimpleArtifactRepository extends SimpleArtifactRepository {
+ boolean executeBatch = false;
+
+ /**
+ * @param repositoryName
+ * @param location
+ * @param properties
+ */
+ public FailingSimpleArtifactRepository(String repositoryName, URI location, Map properties) {
+ super(repositoryName, location, properties);
+ }
+
+ public IStatus executeBatch(Runnable runnable) {
+ executeBatch = true;
+ return super.executeBatch(runnable);
+ }
+
+ public void save() {
+ if (executeBatch)
+ throw new RuntimeException("foo");
+ }
+ }
+
+ class FailingCompositeArtifactRepository extends CompositeArtifactRepository {
+ boolean executeBatch = false;
+
+ /**
+ * @param repositoryName
+ * @param location
+ * @param properties
+ */
+ public FailingCompositeArtifactRepository(IArtifactRepositoryManager manager, String repositoryName, URI location, Map properties) {
+ super(manager, location, repositoryName, properties);
+ }
+
+ public IStatus executeBatch(Runnable runnable) {
+ executeBatch = true;
+ return super.executeBatch(runnable);
+ }
+
+ public void save() {
+ if (executeBatch)
+ throw new RuntimeException("foo");
+ }
+ }
+
+ /*
+ * This tests that exceptions are properly propagated for a SimpleArtifactRepository
+ */
+ public void testBatchProcessingExceptionsSimple() {
+ try {
+ SimpleArtifactRepository simpleArtifactRepository = new FailingSimpleArtifactRepository("foo", new URI("http://foo.bar"), null);
+
+ IStatus status = simpleArtifactRepository.executeBatch(new Runnable() {
+ public void run() {
+ throw new RuntimeException("bar");
+ }
+ });
+ assertFalse(status.isOK());
+ assertEquals("foo", status.getException().getMessage());
+ assertEquals(1, status.getChildren().length);
+ assertEquals("bar", status.getChildren()[0].getMessage());
+ } catch (Exception e) {
+ fail("Test failed", e);
+ }
+ }
+
+ /*
+ * This tests that exceptions are properly propagated for a SimpleArtifactRepository
+ */
+ public void testBatchProcessingSaveExceptionSimple() {
+ try {
+ SimpleArtifactRepository simpleArtifactRepository = new FailingSimpleArtifactRepository("foo", new URI("http://foo.bar"), null);
+
+ IStatus status = simpleArtifactRepository.executeBatch(new Runnable() {
+ public void run() {
+ // empty
+ }
+ });
+ assertFalse(status.isOK());
+ assertEquals("foo", status.getException().getMessage());
+ } catch (Exception e) {
+ fail("Test failed", e);
+ }
+ }
+
+ /*
+ * This tests that exceptions are properly propagated for a CompositeRepository
+ */
+ public void testBatchProcessingExceptionsComposite() {
+ try {
+ FailingCompositeArtifactRepository compositeArtifactRepository = new FailingCompositeArtifactRepository(getArtifactRepositoryManager(), "foo", new URI("http://foo.bar"), null);
+
+ IStatus status = compositeArtifactRepository.executeBatch(new Runnable() {
+ public void run() {
+ throw new RuntimeException("bar");
+ }
+ });
+ assertFalse(status.isOK());
+ assertEquals("foo", status.getException().getMessage());
+ assertEquals(1, status.getChildren().length);
+ assertEquals("bar", status.getChildren()[0].getMessage());
+ } catch (Exception e) {
+ fail("Test failed", e);
+ }
+ }
+
+ /*
+ * This tests that exceptions are properly propagated for a CompositeRepository
+ */
+ public void testBatchProcessingSaveExceptionComposite() {
+ try {
+ FailingCompositeArtifactRepository compositeArtifactRepository = new FailingCompositeArtifactRepository(getArtifactRepositoryManager(), "foo", new URI("http://foo.bar"), null);
+
+ IStatus status = compositeArtifactRepository.executeBatch(new Runnable() {
+ public void run() {
+ // empty
+ }
+ });
+ assertFalse(status.isOK());
+ assertEquals("foo", status.getException().getMessage());
+ } catch (Exception e) {
+ fail("Test failed", e);
+ }
+ }
+
+ class TrackSavignSimpleArtifactRepository extends SimpleArtifactRepository {
+ boolean executeBatch = false;
+ public boolean didSave = false;
+
+ /**
+ * @param repositoryName
+ * @param location
+ * @param properties
+ */
+ public TrackSavignSimpleArtifactRepository(String repositoryName, URI location, Map properties) {
+ super(repositoryName, location, properties);
+ }
+
+ public IStatus executeBatch(Runnable runnable) {
+ executeBatch = true;
+ return super.executeBatch(runnable);
+ }
+
+ public void save() {
+ if (executeBatch)
+ didSave = true;
+ }
+ }
+
+ /*
+ * This test ensure that a repository did in fact save the results,
+ * if there was no exception
+ */
+ public void testBatchProcessingTrackSaving() {
+ try {
+ TrackSavignSimpleArtifactRepository simpleArtifactRepository = new TrackSavignSimpleArtifactRepository("foo", new URI("http://foo.bar"), null);
+ simpleArtifactRepository.executeBatch(new Runnable() {
+ public void run() {
+ //do nothing;
+ }
+ });
+ assertTrue(simpleArtifactRepository.didSave);
+ } catch (Exception e) {
+ fail("Test failed", e);
+ }
+ }
+
+ /*
+ * This test ensures that a repository did in fact save the results, even
+ * if there was an exception
+ */
+ public void testBatchProcessingTrackSavingException() {
+ try {
+ TrackSavignSimpleArtifactRepository simpleArtifactRepository = new TrackSavignSimpleArtifactRepository("foo", new URI("http://foo.bar"), null);
+ simpleArtifactRepository.executeBatch(new Runnable() {
+ public void run() {
+ throw new RuntimeException();
+ }
+ });
+ assertTrue(simpleArtifactRepository.didSave);
+ } catch (Exception e) {
+ fail("Test failed", e);
+ }
+ }
+
+ /*
+ * This test ensures that the simple repository resets the disableSave flag
+ * even if there is an exception
+ */
+ public void testDisableSaveFlagResetSimple() {
+ try {
+ repositoryFile = getTempFolder();
+ repositoryURI = repositoryFile.toURI();
+ Map properties = new HashMap();
+ SimpleArtifactRepository repo = (SimpleArtifactRepository) getArtifactRepositoryManager().createRepository(repositoryURI, "My Repo", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
+ repo.executeBatch(new Runnable() {
+ public void run() {
+ throw new RuntimeException();
+ }
+ });
+ Field field = SimpleArtifactRepository.class.getDeclaredField("disableSave");
+ field.setAccessible(true);
+ boolean disableSave = field.getBoolean(repo);
+ assertFalse("1.0", disableSave);
+
+ } catch (Exception e) {
+ fail("Test failed", e);
+ }
+ }
+
+ /*
+ * This test ensure that the simple artifact repository disables the
+ * save flag during the batch process
+ */
+ public void testDisableSaveFlagDuringExecutionSimple() {
+ try {
+ repositoryFile = getTempFolder();
+ repositoryURI = repositoryFile.toURI();
+ Map properties = new HashMap();
+ final SimpleArtifactRepository repo = (SimpleArtifactRepository) getArtifactRepositoryManager().createRepository(repositoryURI, "My Repo", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
+ repo.executeBatch(new Runnable() {
+ public void run() {
+ Field field;
+ try {
+ field = SimpleArtifactRepository.class.getDeclaredField("disableSave");
+ field.setAccessible(true);
+ boolean disableSave = field.getBoolean(repo);
+ assertTrue("1.0", disableSave);
+ } catch (SecurityException e) {
+ fail("1.1" + e.getMessage());
+ } catch (NoSuchFieldException e) {
+ // TODO Auto-generated catch block
+ fail("1.2" + e.getMessage());
+ } catch (IllegalArgumentException e) {
+ fail("1.2" + e.getMessage());
+ } catch (IllegalAccessException e) {
+ fail("1.2" + e.getMessage());
+ }
+ }
+ });
+
+ } catch (Exception e) {
+ fail("Test failed", e);
+ }
+ }
+
+ /**
+ * This tests ensure that the composite repository sets the disableSave flag
+ * back, even if there is an exception
+ */
+ public void testDisableSaveFlagResetComposite() {
+ try {
+ repositoryFile = getTempFolder();
+ repositoryURI = repositoryFile.toURI();
+ Map properties = new HashMap();
+ CompositeArtifactRepository repo = (CompositeArtifactRepository) getArtifactRepositoryManager().createRepository(repositoryURI, "My Repo", IArtifactRepositoryManager.TYPE_COMPOSITE_REPOSITORY, properties);
+ repo.executeBatch(new Runnable() {
+ public void run() {
+ throw new RuntimeException();
+ }
+ });
+ Field field = CompositeArtifactRepository.class.getDeclaredField("disableSave");
+ field.setAccessible(true);
+ boolean disableSave = field.getBoolean(repo);
+ assertFalse("1.0", disableSave);
+
+ } catch (Exception e) {
+ fail("Test failed", e);
+ }
+ }
+
+ /*
+ * This test makes sure that the composite repository save is disabled during write
+ */
+ public void testDisableSaveFlagDuringExecutionComposite() {
+ try {
+ repositoryFile = getTempFolder();
+ repositoryURI = repositoryFile.toURI();
+ Map properties = new HashMap();
+ final CompositeArtifactRepository repo = (CompositeArtifactRepository) getArtifactRepositoryManager().createRepository(repositoryURI, "My Repo", IArtifactRepositoryManager.TYPE_COMPOSITE_REPOSITORY, properties);
+ repo.executeBatch(new Runnable() {
+ public void run() {
+ Field field;
+ try {
+ field = CompositeArtifactRepository.class.getDeclaredField("disableSave");
+ field.setAccessible(true);
+ boolean disableSave = field.getBoolean(repo);
+ assertTrue("1.0", disableSave);
+ } catch (SecurityException e) {
+ fail("1.1" + e.getMessage());
+ } catch (NoSuchFieldException e) {
+ // TODO Auto-generated catch block
+ fail("1.2" + e.getMessage());
+ } catch (IllegalArgumentException e) {
+ fail("1.2" + e.getMessage());
+ } catch (IllegalAccessException e) {
+ fail("1.2" + e.getMessage());
+ }
+ }
+ });
+
+ } catch (Exception e) {
+ fail("Test failed", e);
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/SimpleArtifactRepositoryTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/SimpleArtifactRepositoryTest.java
index ad1d357d1..75e0082ef 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/SimpleArtifactRepositoryTest.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/SimpleArtifactRepositoryTest.java
@@ -12,9 +12,6 @@
*******************************************************************************/
package org.eclipse.equinox.p2.tests.artifact.repository;
-import org.eclipse.equinox.p2.metadata.Version;
-import org.eclipse.equinox.p2.metadata.VersionRange;
-
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
@@ -26,7 +23,7 @@ import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.processing.ProcessingStep;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.processing.ProcessingStepHandler;
import org.eclipse.equinox.p2.core.ProvisionException;
-import org.eclipse.equinox.p2.metadata.IArtifactKey;
+import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.query.IQueryable;
import org.eclipse.equinox.p2.repository.IRepository;
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/TestArtifactRepository.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/TestArtifactRepository.java
index aef0693c2..85c4332eb 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/TestArtifactRepository.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/TestArtifactRepository.java
@@ -307,4 +307,13 @@ public class TestArtifactRepository implements IArtifactRepository {
}
};
}
+
+ public IStatus executeBatch(Runnable runnable) {
+ try {
+ runnable.run();
+ } catch (Exception e) {
+ return new Status(IStatus.ERROR, "org.eclipse.equinox.p2.tests.publisher", e.getMessage(), e);
+ }
+ return Status.OK_STATUS;
+ }
} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/artifact/UpdateSiteArtifactRepository.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/artifact/UpdateSiteArtifactRepository.java
index d8ba4e035..cd3f4566e 100644
--- a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/artifact/UpdateSiteArtifactRepository.java
+++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/artifact/UpdateSiteArtifactRepository.java
@@ -146,4 +146,8 @@ public class UpdateSiteArtifactRepository implements IArtifactRepository {
public IQueryResult<IArtifactKey> query(IQuery<IArtifactKey> query, IProgressMonitor monitor) {
return delegate.query(query, monitor);
}
+
+ public IStatus executeBatch(Runnable runnable) {
+ return delegate.executeBatch(runnable);
+ }
}

Back to the top