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
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.
-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