Bug 221031 Directory watcher to support repositories
diff --git a/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/RepositoryListener.java b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/RepositoryListener.java
index 842fd5d..7087ac0 100644
--- a/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/RepositoryListener.java
+++ b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/RepositoryListener.java
@@ -21,10 +21,8 @@
import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
-import org.eclipse.equinox.internal.provisional.p2.metadata.query.InstallableUnitQuery;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
-import org.eclipse.equinox.internal.provisional.p2.query.Collector;
import org.eclipse.equinox.internal.provisional.p2.query.Query;
import org.eclipse.osgi.service.resolver.*;
import org.osgi.framework.BundleContext;
@@ -32,13 +30,14 @@
public class RepositoryListener extends DirectoryChangeListener {
+ private static final String ARTIFACT_FOLDER = "artifact.folder"; //$NON-NLS-1$
+ private static final String ARTIFACT_REFERENCE = "artifact.reference"; //$NON-NLS-1$
+ private static final String FILE_LAST_MODIFIED = "file.lastModified"; //$NON-NLS-1$
+ private static final String FILE_NAME = "file.name"; //$NON-NLS-1$
private final IMetadataRepository metadataRepository;
private final IArtifactRepository artifactRepository;
private final BundleDescriptionFactory bundleDescriptionFactory;
private final Map currentFiles = new HashMap();
- private final String repositoryName;
- private final boolean hidden;
- private long lastModifed;
/**
* Create a repository listener that watches the specified folder and generates repositories
@@ -51,11 +50,9 @@
*/
public RepositoryListener(BundleContext context, String repositoryName, File repositoryFolder, boolean hidden) {
- this.repositoryName = repositoryName;
- this.hidden = hidden;
File stateDir;
if (repositoryFolder == null) {
- String stateDirName = "listener_" + repositoryName;
+ String stateDirName = "listener_" + repositoryName.hashCode();
stateDir = context.getDataFile(stateDirName);
stateDir.mkdirs();
} else {
@@ -69,13 +66,19 @@
throw new IllegalStateException(e.getMessage());
}
- metadataRepository = initializeMetadataRepository(context, stateDirURL);
- artifactRepository = initializeArtifactRepository(context, stateDirURL);
+ metadataRepository = initializeMetadataRepository(context, repositoryName, stateDirURL, hidden);
+ artifactRepository = initializeArtifactRepository(context, repositoryName, stateDirURL, hidden);
bundleDescriptionFactory = initializeBundleDescriptionFactory(context);
}
- public RepositoryListener(BundleContext context, String string) {
- this(context, string, null, false);
+ public RepositoryListener(BundleContext context, String repositoryName) {
+ this(context, repositoryName, null, false);
+ }
+
+ public RepositoryListener(BundleContext context, IMetadataRepository metadataRepository, IArtifactRepository artifactRepository) {
+ this.artifactRepository = artifactRepository;
+ this.metadataRepository = metadataRepository;
+ bundleDescriptionFactory = initializeBundleDescriptionFactory(context);
}
private BundleDescriptionFactory initializeBundleDescriptionFactory(BundleContext context) {
@@ -95,7 +98,7 @@
}
}
- private IArtifactRepository initializeArtifactRepository(BundleContext context, URL stateDirURL) {
+ private IArtifactRepository initializeArtifactRepository(BundleContext context, String repositoryName, URL stateDirURL, boolean hidden) {
ServiceReference reference = context.getServiceReference(IArtifactRepositoryManager.class.getName());
IArtifactRepositoryManager manager = null;
if (reference != null)
@@ -129,7 +132,7 @@
}
}
- private IMetadataRepository initializeMetadataRepository(BundleContext context, URL stateDirURL) {
+ private IMetadataRepository initializeMetadataRepository(BundleContext context, String repositoryName, URL stateDirURL, boolean hidden) {
ServiceReference reference = context.getServiceReference(IMetadataRepositoryManager.class.getName());
IMetadataRepositoryManager manager = null;
if (reference != null)
@@ -150,6 +153,7 @@
} else {
repository = manager.createRepository(stateDirURL, repositoryName, IMetadataRepositoryManager.TYPE_SIMPLE_REPOSITORY);
}
+ manager.addRepository(stateDirURL);
return repository;
} catch (ProvisionException e) {
LogHelper.log(e);
@@ -163,8 +167,7 @@
* @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.IDirectoryChangeListener#added(java.io.File)
*/
public boolean added(File file) {
- if (isInteresting(file))
- currentFiles.put(file, new Long(file.lastModified()));
+ currentFiles.put(file, new Long(file.lastModified()));
return true;
}
@@ -172,8 +175,7 @@
* @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.IDirectoryChangeListener#changed(java.io.File)
*/
public boolean changed(File file) {
- if (isInteresting(file))
- currentFiles.put(file, new Long(file.lastModified()));
+ currentFiles.put(file, new Long(file.lastModified()));
return true;
}
@@ -187,19 +189,23 @@
return true;
}
- /*
- * Return a boolean value indicating whether or not we are interested in
- * processing the given file. Currently we handle JAR files and directories.
- */
- private boolean isInteresting(File file) {
- return file.isDirectory() || file.getAbsolutePath().endsWith(".jar");
+ private boolean isBundle(File file) {
+ if (file.isDirectory() || file.getName().endsWith(".jar")) {
+ BundleDescription bundleDescription = bundleDescriptionFactory.getBundleDescription(file);
+ return bundleDescription != null;
+ }
+ return false;
+ }
+
+ private boolean isFeature(File file) {
+ return file.isDirectory() && new File(file, "feature.xml").exists();
}
/* (non-Javadoc)
* @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryChangeListener#isInterested(java.io.File)
*/
public boolean isInterested(File file) {
- return true;
+ return isFeature(file) || isBundle(file);
}
/* (non-Javadoc)
@@ -220,93 +226,89 @@
* @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.IDirectoryChangeListener#stopPoll()
*/
public void stopPoll() {
- synchronizeMetadataRepository();
- synchronizeArtifactRepository();
+ if (metadataRepository != null)
+ synchronizeMetadataRepository();
+
+ if (artifactRepository != null)
+ synchronizeArtifactRepository();
}
private void synchronizeMetadataRepository() {
- boolean modified = false;
final Map snapshot = new HashMap(currentFiles);
Query removeQuery = new Query() {
public boolean isMatch(Object candidate) {
if (!(candidate instanceof IInstallableUnit))
return false;
IInstallableUnit iu = (IInstallableUnit) candidate;
- File iuFile = new File(iu.getProperty("file.name")); //$NON-NLS-1$
- Long iuLastModified = new Long(iu.getProperty("file.lastModified")); //$NON-NLS-1$
+ File iuFile = new File(iu.getProperty(FILE_NAME));
+ Long iuLastModified = new Long(iu.getProperty(FILE_LAST_MODIFIED));
Long snapshotLastModified = (Long) snapshot.get(iuFile);
if (snapshotLastModified == null || !snapshotLastModified.equals(iuLastModified))
return true;
+
+ // match found. Remove from snapshot to prevent it from being added.
snapshot.remove(iuFile);
return false;
}
};
- if (metadataRepository.removeInstallableUnits(removeQuery, null))
- modified = true;
+ metadataRepository.removeInstallableUnits(removeQuery, null);
if (!snapshot.isEmpty()) {
- modified = true;
- IInstallableUnit[] iusToAdd = generateIUs(snapshot.keySet(), metadataRepository.getLocation().toExternalForm());
+ IInstallableUnit[] iusToAdd = generateIUs(snapshot.keySet());
metadataRepository.addInstallableUnits(iusToAdd);
}
- if (modified)
- lastModifed = System.currentTimeMillis();
}
private void synchronizeArtifactRepository() {
- final boolean[] modified = {false};
- final List snapshot = new ArrayList(Arrays.asList(artifactRepository.getArtifactKeys()));
- Collector collector = new Collector() {
- public boolean accept(Object object) {
- IInstallableUnit iu = (IInstallableUnit) object;
- IArtifactKey[] artifacts = iu.getArtifacts();
- if (artifacts == null || artifacts.length == 0)
- return true;
- IArtifactKey artifact = artifacts[0];
- if (!snapshot.remove(artifact)) {
- File iuFile = new File(iu.getProperty("file.name"));
- IArtifactDescriptor descriptor = generateArtifactDescriptor(iuFile);
- if (descriptor != null) {
- artifactRepository.addDescriptor(descriptor);
- modified[0] = true;
- }
- }
- return true;
- }
- };
- metadataRepository.query(InstallableUnitQuery.ANY, collector, null);
+ final Map snapshot = new HashMap(currentFiles);
+ final List keys = new ArrayList(Arrays.asList(artifactRepository.getArtifactKeys()));
- for (Iterator it = snapshot.iterator(); it.hasNext();) {
+ for (Iterator it = keys.iterator(); it.hasNext();) {
IArtifactKey key = (IArtifactKey) it.next();
- artifactRepository.removeDescriptor(key);
- modified[0] = true;
+ IArtifactDescriptor[] descriptors = artifactRepository.getArtifactDescriptors(key);
+ for (int i = 0; i < descriptors.length; i++) {
+ ArtifactDescriptor descriptor = (ArtifactDescriptor) descriptors[i];
+ File artifactFile = new File(descriptor.getRepositoryProperty(FILE_NAME));
+ Long artifactLastModified = new Long(descriptor.getRepositoryProperty(FILE_LAST_MODIFIED));
+ Long snapshotLastModified = (Long) snapshot.get(artifactFile);
+ if (snapshotLastModified == null || !snapshotLastModified.equals(artifactLastModified))
+ artifactRepository.removeDescriptor(descriptor);
+ else
+ snapshot.remove(key);
+ }
}
- if (modified[0])
- lastModifed = System.currentTimeMillis();
+ for (Iterator it = snapshot.keySet().iterator(); it.hasNext();) {
+ File file = (File) it.next();
+ IArtifactDescriptor descriptor = generateArtifactDescriptor(file);
+ if (descriptor != null)
+ artifactRepository.addDescriptor(descriptor);
+ }
}
- IArtifactDescriptor generateArtifactDescriptor(File candidate) {
+ protected IArtifactDescriptor generateArtifactDescriptor(File candidate) {
IArtifactDescriptor basicDescriptor = generateBasicDescriptor(candidate);
ArtifactDescriptor pathDescriptor = new ArtifactDescriptor(basicDescriptor);
try {
- pathDescriptor.setRepositoryProperty("artifact.reference", candidate.toURL().toExternalForm());
+ pathDescriptor.setRepositoryProperty(ARTIFACT_REFERENCE, candidate.toURL().toExternalForm());
} catch (MalformedURLException e) {
// unexpected
e.printStackTrace();
return null;
}
if (candidate.isDirectory())
- pathDescriptor.setRepositoryProperty("artifact.folder", "true");
+ pathDescriptor.setRepositoryProperty(ARTIFACT_FOLDER, Boolean.TRUE.toString());
+
+ pathDescriptor.setRepositoryProperty(FILE_NAME, candidate.getAbsolutePath());
+ pathDescriptor.setRepositoryProperty(FILE_LAST_MODIFIED, Long.toString(candidate.lastModified()));
return pathDescriptor;
}
private IArtifactDescriptor generateBasicDescriptor(File candidate) {
- // feature check
- File parent = candidate.getParentFile();
- if (parent != null && parent.getName().equals("features")) {
+
+ if (isFeature(candidate)) {
FeatureParser parser = new FeatureParser();
Feature feature = parser.parse(candidate);
IArtifactKey featureKey = MetadataGeneratorHelper.createFeatureArtifactKey(feature.getId(), feature.getVersion());
@@ -318,22 +320,16 @@
return MetadataGeneratorHelper.createArtifactDescriptor(key, candidate, true, false);
}
- private IInstallableUnit[] generateIUs(Collection files, String repositoryId) {
+ private IInstallableUnit[] generateIUs(Collection files) {
List ius = new ArrayList();
for (Iterator it = files.iterator(); it.hasNext();) {
File candidate = (File) it.next();
Properties props = new Properties();
- props.setProperty("repository.id", repositoryId);
- props.setProperty("file.name", candidate.getAbsolutePath());
- props.setProperty("file.lastModified", Long.toString(candidate.lastModified()));
+ props.setProperty(FILE_NAME, candidate.getAbsolutePath());
+ props.setProperty(FILE_LAST_MODIFIED, Long.toString(candidate.lastModified()));
- if (candidate.isDirectory() && candidate.getName().equals("eclipse"))
- continue;
-
- // feature check
- File parent = candidate.getParentFile();
- if (parent != null && parent.getName().equals("features")) {
+ if (isFeature(candidate)) {
IInstallableUnit[] featureIUs = generateFeatureIUs(candidate, props);
if (featureIUs != null)
ius.addAll(Arrays.asList(featureIUs));
@@ -378,8 +374,4 @@
public IArtifactRepository getArtifactRepository() {
return artifactRepository;
}
-
- public long getLastModified() {
- return lastModifed;
- }
}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.reconciler.dropins/META-INF/MANIFEST.MF
index 15e1965..3746432 100644
--- a/bundles/org.eclipse.equinox.p2.reconciler.dropins/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.reconciler.dropins/META-INF/MANIFEST.MF
@@ -6,7 +6,6 @@
Bundle-Localization: plugin
Bundle-Version: 0.1.0.qualifier
Bundle-Activator: org.eclipse.equinox.internal.p2.reconciler.dropins.Activator
-Eclipse-LazyStart: true
Bundle-RequiredExecutionEnvironment: J2SE-1.4,
CDC-1.1/Foundation-1.1
Import-Package: org.eclipse.equinox.internal.p2.update,
@@ -21,6 +20,9 @@
org.eclipse.equinox.internal.provisional.p2.metadata.query,
org.eclipse.equinox.internal.provisional.p2.metadata.repository,
org.eclipse.equinox.internal.provisional.p2.query,
+ org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository,
+ org.eclipse.equinox.internal.provisional.spi.p2.core.repository,
+ org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository,
org.eclipse.osgi.service.datalocation;version="1.0.0",
org.eclipse.osgi.util;version="1.1.0",
org.osgi.framework;version="1.3.0",
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/build.properties b/bundles/org.eclipse.equinox.p2.reconciler.dropins/build.properties
index 97493b2..eb63c6e 100644
--- a/bundles/org.eclipse.equinox.p2.reconciler.dropins/build.properties
+++ b/bundles/org.eclipse.equinox.p2.reconciler.dropins/build.properties
@@ -13,4 +13,5 @@
bin.includes = META-INF/,\
.,\
plugin.properties,\
- about.html
+ about.html,\
+ plugin.xml
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/plugin.xml b/bundles/org.eclipse.equinox.p2.reconciler.dropins/plugin.xml
new file mode 100644
index 0000000..81c2c8e
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.reconciler.dropins/plugin.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+ <extension
+ id="extensionRepository"
+ point="org.eclipse.equinox.p2.metadata.repository.metadataRepositories">
+ <factory
+ class="org.eclipse.equinox.internal.p2.extensionlocation.ExtensionLocationMetadataRepositoryFactory">
+ </factory>
+ <filter
+ suffix="eclipse">
+ </filter>
+ </extension>
+ <extension
+ point="org.eclipse.equinox.p2.artifact.repository.artifactRepositories">
+ <factory
+ class="org.eclipse.equinox.internal.p2.extensionlocation.ExtensionLocationArtifactRepositoryFactory">
+ </factory>
+ <filter
+ suffix="eclipse">
+ </filter>
+ </extension>
+</plugin>
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepository.java b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepository.java
new file mode 100644
index 0000000..8d6581b
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepository.java
@@ -0,0 +1,151 @@
+package org.eclipse.equinox.internal.p2.extensionlocation;
+
+import java.io.File;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.reconciler.dropins.Activator;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.*;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
+import org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryWatcher;
+import org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener;
+import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey;
+import org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository.SimpleArtifactRepositoryFactory;
+import org.eclipse.equinox.internal.provisional.spi.p2.core.repository.AbstractRepository;
+import org.osgi.framework.BundleContext;
+
+public class ExtensionLocationArtifactRepository extends AbstractRepository implements IFileArtifactRepository {
+
+ //private static final String PROFILE_EXTENSION = "profile.extension"; //$NON-NLS-1$
+ private static final String ECLIPSE = "eclipse"; //$NON-NLS-1$
+ private static final String FEATURES = "features"; //$NON-NLS-1$
+ private static final String PLUGINS = "plugins"; //$NON-NLS-1$
+ private static final String FILE = "file"; //$NON-NLS-1$
+ private final IFileArtifactRepository artifactRepository;
+
+ public ExtensionLocationArtifactRepository(URL location, IProgressMonitor monitor) throws ProvisionException {
+ super("Extension: " + location.toExternalForm(), null, null, location, null, null); //$NON-NLS-1$
+
+ File base = getBaseDirectory(location);
+ File plugins = new File(base, PLUGINS);
+ File features = new File(base, FEATURES);
+
+ BundleContext context = Activator.getContext();
+ String stateDirName = Integer.toString(location.toExternalForm().hashCode());
+ File bundleData = context.getDataFile(null);
+ File stateDir = new File(bundleData, stateDirName);
+ URL localRepositoryURL;
+ try {
+ localRepositoryURL = stateDir.toURL();
+ } catch (MalformedURLException e) {
+ // unexpected
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, "Failed to create local repository", e)); //$NON-NLS-1$
+ }
+
+ artifactRepository = (IFileArtifactRepository) initializeArtifactRepository(localRepositoryURL, "extension location implementation - " + location.toExternalForm()); //$NON-NLS-1$
+
+ DirectoryWatcher watcher = new DirectoryWatcher(new File[] {plugins, features});
+ RepositoryListener listener = new RepositoryListener(context, null, artifactRepository);
+ watcher.addListener(listener);
+ watcher.poll();
+ }
+
+ private IArtifactRepository initializeArtifactRepository(URL stateDirURL, String repositoryName) {
+ SimpleArtifactRepositoryFactory factory = new SimpleArtifactRepositoryFactory();
+ try {
+ return factory.load(stateDirURL, null);
+
+ } catch (ProvisionException e) {
+ //fall through and create a new repository
+ }
+ IArtifactRepository repository = factory.create(stateDirURL, repositoryName, null);
+ //repository.setProperty(PROFILE_EXTENSION, "true");
+ return repository;
+ }
+
+ public static void validate(URL location, IProgressMonitor monitor) throws ProvisionException {
+ getBaseDirectory(location);
+ }
+
+ public static File getBaseDirectory(URL url) throws ProvisionException {
+ if (url.getProtocol() != FILE)
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, "location must use file protocol", null));
+
+ File base = new File(url.getPath());
+ if (!base.isDirectory())
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, "location not a directory", null));
+
+ if (isBaseDirectory(base))
+ return base;
+
+ File eclipseBase = new File(base, ECLIPSE);
+ if (isBaseDirectory(eclipseBase))
+ return eclipseBase;
+
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, "location is not an extension", null));
+ }
+
+ private static boolean isBaseDirectory(File base) {
+ File plugins = new File(base, PLUGINS);
+ File features = new File(base, FEATURES);
+
+ return plugins.isDirectory() || features.isDirectory();
+ }
+
+ public void addDescriptor(IArtifactDescriptor descriptor) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void addDescriptors(IArtifactDescriptor[] descriptors) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void removeAll() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void removeDescriptor(IArtifactDescriptor descriptor) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void removeDescriptor(IArtifactKey key) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean contains(IArtifactDescriptor descriptor) {
+ return artifactRepository.contains(descriptor);
+ }
+
+ public boolean contains(IArtifactKey key) {
+ return artifactRepository.contains(key);
+ }
+
+ public IStatus getArtifact(IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) {
+ return artifactRepository.getArtifact(descriptor, destination, monitor);
+ }
+
+ public IArtifactDescriptor[] getArtifactDescriptors(IArtifactKey key) {
+ return artifactRepository.getArtifactDescriptors(key);
+ }
+
+ public IArtifactKey[] getArtifactKeys() {
+ return artifactRepository.getArtifactKeys();
+ }
+
+ public IStatus getArtifacts(IArtifactRequest[] requests, IProgressMonitor monitor) {
+ return artifactRepository.getArtifacts(requests, monitor);
+ }
+
+ public OutputStream getOutputStream(IArtifactDescriptor descriptor) throws ProvisionException {
+ return artifactRepository.getOutputStream(descriptor);
+ }
+
+ public File getArtifactFile(IArtifactKey key) {
+ return artifactRepository.getArtifactFile(key);
+ }
+
+ public File getArtifactFile(IArtifactDescriptor descriptor) {
+ return artifactRepository.getArtifactFile(descriptor);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepositoryFactory.java b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepositoryFactory.java
new file mode 100644
index 0000000..83cb924
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepositoryFactory.java
@@ -0,0 +1,28 @@
+package org.eclipse.equinox.internal.p2.extensionlocation;
+
+import java.net.URL;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
+import org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository.IArtifactRepositoryFactory;
+
+public class ExtensionLocationArtifactRepositoryFactory implements IArtifactRepositoryFactory {
+
+ public IArtifactRepository create(URL location, String name, String type) throws ProvisionException {
+ return null;
+ }
+
+ public IArtifactRepository load(URL location, IProgressMonitor monitor) throws ProvisionException {
+ return new ExtensionLocationArtifactRepository(location, monitor);
+ }
+
+ public IStatus validate(URL location, IProgressMonitor monitor) {
+ try {
+ ExtensionLocationArtifactRepository.validate(location, monitor);
+ } catch (ProvisionException e) {
+ return e.getStatus();
+ }
+ return Status.OK_STATUS;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepository.java b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepository.java
new file mode 100644
index 0000000..8004e2d
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepository.java
@@ -0,0 +1,108 @@
+package org.eclipse.equinox.internal.p2.extensionlocation;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.reconciler.dropins.Activator;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
+import org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryWatcher;
+import org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener;
+import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
+import org.eclipse.equinox.internal.provisional.p2.query.Collector;
+import org.eclipse.equinox.internal.provisional.p2.query.Query;
+import org.eclipse.equinox.internal.provisional.spi.p2.core.repository.AbstractRepository;
+import org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.SimpleMetadataRepositoryFactory;
+import org.osgi.framework.BundleContext;
+
+public class ExtensionLocationMetadataRepository extends AbstractRepository implements IMetadataRepository {
+
+ private static final String ECLIPSE = "eclipse"; //$NON-NLS-1$
+ private static final String FEATURES = "features"; //$NON-NLS-1$
+ private static final String PLUGINS = "plugins"; //$NON-NLS-1$
+ private static final String FILE = "file"; //$NON-NLS-1$
+ private final IMetadataRepository metadataRepository;
+
+ public ExtensionLocationMetadataRepository(URL location, IProgressMonitor monitor) throws ProvisionException {
+ super("Extension: " + location.toExternalForm(), null, null, location, null, null); //$NON-NLS-1$
+
+ File base = getBaseDirectory(location);
+ File plugins = new File(base, PLUGINS);
+ File features = new File(base, FEATURES);
+
+ BundleContext context = Activator.getContext();
+ String stateDirName = Integer.toString(location.toExternalForm().hashCode());
+ File bundleData = context.getDataFile(null);
+ File stateDir = new File(bundleData, stateDirName);
+ URL localRepositoryURL;
+ try {
+ localRepositoryURL = stateDir.toURL();
+ } catch (MalformedURLException e) {
+ // unexpected
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, "Failed to create local repository", e)); //$NON-NLS-1$
+ }
+
+ metadataRepository = initializeMetadataRepository(localRepositoryURL, "extension location implementation - " + location.toExternalForm()); //$NON-NLS-1$
+
+ DirectoryWatcher watcher = new DirectoryWatcher(new File[] {plugins, features});
+ RepositoryListener listener = new RepositoryListener(context, metadataRepository, null);
+ watcher.addListener(listener);
+ watcher.poll();
+ }
+
+ private IMetadataRepository initializeMetadataRepository(URL stateDirURL, String repositoryName) {
+ SimpleMetadataRepositoryFactory factory = new SimpleMetadataRepositoryFactory();
+ try {
+ return factory.load(stateDirURL, null);
+ } catch (ProvisionException e) {
+ //fall through and create a new repository
+ }
+ return factory.create(stateDirURL, repositoryName, null);
+ }
+
+ public void addInstallableUnits(IInstallableUnit[] installableUnits) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void removeAll() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean removeInstallableUnits(Query query, IProgressMonitor monitor) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Collector query(Query query, Collector collector, IProgressMonitor monitor) {
+ return metadataRepository.query(query, collector, monitor);
+ }
+
+ public static void validate(URL location, IProgressMonitor monitor) throws ProvisionException {
+ getBaseDirectory(location);
+ }
+
+ public static File getBaseDirectory(URL url) throws ProvisionException {
+ if (url.getProtocol() != FILE)
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, "location must use file protocol", null));
+
+ File base = new File(url.getPath());
+ if (!base.isDirectory())
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, "location not a directory", null));
+
+ if (isBaseDirectory(base))
+ return base;
+
+ File eclipseBase = new File(base, ECLIPSE);
+ if (isBaseDirectory(eclipseBase))
+ return eclipseBase;
+
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, "location is not an extension", null));
+ }
+
+ private static boolean isBaseDirectory(File base) {
+ File plugins = new File(base, PLUGINS);
+ File features = new File(base, FEATURES);
+
+ return plugins.isDirectory() || features.isDirectory();
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepositoryFactory.java b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepositoryFactory.java
new file mode 100644
index 0000000..31da09c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepositoryFactory.java
@@ -0,0 +1,28 @@
+package org.eclipse.equinox.internal.p2.extensionlocation;
+
+import java.net.URL;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
+import org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.IMetadataRepositoryFactory;
+
+public class ExtensionLocationMetadataRepositoryFactory implements IMetadataRepositoryFactory {
+
+ public IMetadataRepository create(URL location, String name, String type) throws ProvisionException {
+ return null;
+ }
+
+ public IMetadataRepository load(URL location, IProgressMonitor monitor) throws ProvisionException {
+ return new ExtensionLocationMetadataRepository(location, monitor);
+ }
+
+ public IStatus validate(URL location, IProgressMonitor monitor) {
+ try {
+ ExtensionLocationMetadataRepository.validate(location, monitor);
+ } catch (ProvisionException e) {
+ return e.getStatus();
+ }
+ return Status.OK_STATUS;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/Activator.java b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/Activator.java
index 1a46573..bddfb05 100644
--- a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/Activator.java
+++ b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/Activator.java
@@ -14,26 +14,75 @@
import java.net.URL;
import java.util.*;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepositoryManager;
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
import org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryWatcher;
-import org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener;
import org.eclipse.equinox.internal.provisional.p2.engine.IProfile;
import org.eclipse.equinox.internal.provisional.p2.engine.IProfileRegistry;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
import org.osgi.framework.*;
import org.osgi.service.packageadmin.PackageAdmin;
public class Activator implements BundleActivator {
+ public static final String ID = "org.eclipse.equinox.p2.reconciler.dropins"; //$NON-NLS-1$
private static final String DROPINS_DIRECTORY = "org.eclipse.equinox.p2.reconciler.dropins.directory"; //$NON-NLS-1$
private static final String OSGI_CONFIGURATION_AREA = "osgi.configuration.area"; //$NON-NLS-1$
private static final String DROPINS = "dropins"; //$NON-NLS-1$
- private static final String PROFILE_EXTENSION = "profile.extension"; //$NON-NLS-1$
+ // private static final String PROFILE_EXTENSION = "profile.extension"; //$NON-NLS-1$
private static PackageAdmin packageAdmin;
private static BundleContext bundleContext;
private ServiceReference packageAdminRef;
private List watchers = new ArrayList();
- private static IMetadataRepository dropinRepository;
+ private static IMetadataRepository[] dropinRepositories;
+ private static IMetadataRepository[] configurationRepositories;
+ private static IMetadataRepository[] linksRepositories;
+
+ /**
+ * Helper method to load a metadata repository from the specified URL.
+ * This method never returns <code>null</code>.
+ *
+ * @throws IllegalStateException
+ * @throws ProvisionException
+ */
+ public static IMetadataRepository loadMetadataRepository(URL repoURL) throws ProvisionException {
+ BundleContext context = getContext();
+ ServiceReference reference = context.getServiceReference(IMetadataRepositoryManager.class.getName());
+ IMetadataRepositoryManager manager = null;
+ if (reference != null)
+ manager = (IMetadataRepositoryManager) context.getService(reference);
+ if (manager == null)
+ throw new IllegalStateException("MetadataRepositoryManager not registered.");
+ try {
+ return manager.loadRepository(repoURL, null);
+ } finally {
+ context.ungetService(reference);
+ }
+ }
+
+ /**
+ * Helper method to load an artifact repository from the given URL.
+ * This method never returns <code>null</code>.
+ *
+ * @throws IllegalStateException
+ * @throws ProvisionException
+ */
+ public static IArtifactRepository loadArtifactRepository(URL repoURL) throws ProvisionException {
+ BundleContext context = getContext();
+ ServiceReference reference = context.getServiceReference(IArtifactRepositoryManager.class.getName());
+ IArtifactRepositoryManager manager = null;
+ if (reference != null)
+ manager = (IArtifactRepositoryManager) context.getService(reference);
+ if (manager == null)
+ throw new IllegalStateException("ArtifactRepositoryManager not registered.");
+ try {
+ return manager.loadRepository(repoURL, null);
+ } finally {
+ context.ungetService(reference);
+ }
+ }
/* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
@@ -55,9 +104,9 @@
// create the watcher for the "drop-ins" folder
watchDropins(profile);
-
- // create watchers for the sites specified in the platform.xml
- watchConfiguration();
+ // keep an eye on the platform.xml
+ if (false)
+ watchConfiguration();
synchronize(new ArrayList(0), null);
}
@@ -73,14 +122,21 @@
/*
* Synchronize the profile.
*/
- public static void synchronize(List extraRepositories, IProgressMonitor monitor) {
+ public static synchronized void synchronize(List extraRepositories, IProgressMonitor monitor) {
IProfile profile = getCurrentProfile(bundleContext);
if (profile == null)
return;
// create the profile synchronizer on all available repositories
- List repositories = new ArrayList(extraRepositories);
- if (dropinRepository != null)
- repositories.add(dropinRepository);
+ Set repositories = new HashSet(extraRepositories);
+ if (dropinRepositories != null)
+ repositories.addAll(Arrays.asList(dropinRepositories));
+
+ if (configurationRepositories != null)
+ repositories.addAll(Arrays.asList(configurationRepositories));
+
+ if (linksRepositories != null)
+ repositories.addAll(Arrays.asList(linksRepositories));
+
ProfileSynchronizer synchronizer = new ProfileSynchronizer(profile, repositories);
synchronizer.synchronize(monitor);
}
@@ -88,50 +144,43 @@
/*
* Watch the platform.xml file.
*/
- private void watchConfiguration() throws ProvisionException {
+ private void watchConfiguration() {
File configFile = new File("configuration/org.eclipse.update/platform.xml"); //$NON-NLS-1$
DirectoryWatcher watcher = new DirectoryWatcher(configFile.getParentFile());
try {
PlatformXmlListener listener = new PlatformXmlListener(configFile);
watcher.addListener(listener);
+ watcher.poll();
+ List repositories = listener.getMetadataRepositories();
+ if (repositories != null)
+ configurationRepositories = (IMetadataRepository[]) repositories.toArray(new IMetadataRepository[0]);
} catch (ProvisionException e) {
// TODO proper logging
e.printStackTrace();
}
- watchers.add(watcher);
- watcher.start();
-
- // pay attention to the links/ folder too. this is only needed on startup though since
- // any other changes during execution will be reflected in the platform.xml file
- LinksManager manager = new LinksManager();
- manager.synchronize(configFile, new File("links"));
}
/*
* Create a new directory watcher with a repository listener on the drop-ins folder.
*/
private void watchDropins(IProfile profile) {
- File folder = getWatchedDirectory(bundleContext);
- if (folder == null)
+ List directories = new ArrayList();
+ File dropinsDirectory = getDropinsDirectory();
+ if (dropinsDirectory != null)
+ directories.add(dropinsDirectory);
+ File linksDirectory = getLinksDirectory();
+ if (linksDirectory != null)
+ directories.add(linksDirectory);
+ if (directories.isEmpty())
return;
- RepositoryListener listener = new RepositoryListener(Activator.getContext(), Integer.toString(folder.hashCode()));
- listener.getArtifactRepository().setProperty(PROFILE_EXTENSION, profile.getProfileId());
-
- List folders = new ArrayList();
- folders.add(folder);
- File eclipseFeatures = new File(folder, "eclipse/features");
- if (eclipseFeatures.isDirectory())
- folders.add(eclipseFeatures);
- File eclipsePlugins = new File(folder, "eclipse/plugins");
- if (eclipsePlugins.isDirectory())
- folders.add(eclipsePlugins);
-
- DirectoryWatcher watcher = new DirectoryWatcher((File[]) folders.toArray(new File[folders.size()]));
+ DropinsRepositoryListener listener = new DropinsRepositoryListener(Activator.getContext(), "dropins:" + dropinsDirectory.getAbsolutePath());
+ // listener.getArtifactRepository().setProperty(PROFILE_EXTENSION, profile.getProfileId());
+ DirectoryWatcher watcher = new DirectoryWatcher((File[]) directories.toArray(new File[directories.size()]));
watcher.addListener(listener);
watcher.poll();
- dropinRepository = listener.getMetadataRepository();
+ dropinRepositories = listener.getMetadataRepositories();
}
/* (non-Javadoc)
@@ -154,15 +203,27 @@
return bundleContext;
}
- public static File getWatchedDirectory(BundleContext context) {
- String watchedDirectoryProperty = context.getProperty(DROPINS_DIRECTORY);
+ private static File getLinksDirectory() {
+ try {
+ //TODO: a proper install area would be better. osgi.install.area is relative to the framework jar
+ URL baseURL = new URL(bundleContext.getProperty(OSGI_CONFIGURATION_AREA));
+ URL folderURL = new URL(baseURL, "../links"); //$NON-NLS-1$
+ return new File(folderURL.getPath());
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static File getDropinsDirectory() {
+ String watchedDirectoryProperty = bundleContext.getProperty(DROPINS_DIRECTORY);
if (watchedDirectoryProperty != null) {
File folder = new File(watchedDirectoryProperty);
return folder;
}
try {
//TODO: a proper install area would be better. osgi.install.area is relative to the framework jar
- URL baseURL = new URL(context.getProperty(OSGI_CONFIGURATION_AREA));
+ URL baseURL = new URL(bundleContext.getProperty(OSGI_CONFIGURATION_AREA));
URL folderURL = new URL(baseURL, "../" + DROPINS); //$NON-NLS-1$
File folder = new File(folderURL.getPath());
return folder;
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/DropinsRepositoryListener.java b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/DropinsRepositoryListener.java
new file mode 100644
index 0000000..9c4ce05
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/DropinsRepositoryListener.java
@@ -0,0 +1,239 @@
+package org.eclipse.equinox.internal.p2.reconciler.dropins;
+
+import java.io.*;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepositoryManager;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
+import org.eclipse.equinox.internal.provisional.p2.core.repository.IRepository;
+import org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public class DropinsRepositoryListener extends RepositoryListener {
+
+ private static final String DROPIN_ARTIFACT_REPOSITORIES = "dropin.artifactRepositories"; //$NON-NLS-1$
+ private static final String DROPIN_METADATA_REPOSITORIES = "dropin.metadataRepositories"; //$NON-NLS-1$
+ private static final String PIPE = "|"; //$NON-NLS-1$
+ private BundleContext context;
+ private List metadataRepositories = new ArrayList();
+ private List artifactRepositories = new ArrayList();
+
+ public DropinsRepositoryListener(BundleContext context, String repositoryName) {
+ super(context, repositoryName);
+ this.context = context;
+ }
+
+ public boolean isInterested(File file) {
+ if (file.isDirectory())
+ return true;
+
+ String name = file.getName();
+ return name.endsWith(".jar") || name.endsWith(".zip") || name.endsWith(".link");
+ }
+
+ public boolean added(File file) {
+ if (super.isInterested(file))
+ return super.added(file);
+
+ URL repositoryURL = createRepositoryURL(file);
+ if (repositoryURL != null) {
+ loadMetadataRepository(repositoryURL);
+ loadArtifactRepository(repositoryURL);
+ }
+ return true;
+ }
+
+ public boolean changed(File file) {
+ if (super.isInterested(file))
+ return super.added(file);
+
+ URL repositoryURL = createRepositoryURL(file);
+ if (repositoryURL != null) {
+ loadMetadataRepository(repositoryURL);
+ loadArtifactRepository(repositoryURL);
+ }
+ return true;
+ }
+
+ private String getLinkPath(File file) {
+ Properties links = new Properties();
+ try {
+ InputStream input = new BufferedInputStream(new FileInputStream(file));
+ try {
+ links.load(input);
+ } finally {
+ input.close();
+ }
+ } catch (IOException e) {
+ // ignore
+ }
+ String path = links.getProperty("path");
+ if (path == null) {
+ // log
+ return null;
+ }
+
+ // parse out link information
+ if (path.startsWith("r ")) { //$NON-NLS-1$
+ path = path.substring(2).trim();
+ } else if (path.startsWith("rw ")) { //$NON-NLS-1$
+ path = path.substring(3).trim();
+ } else {
+ path = path.trim();
+ }
+ return path;
+ }
+
+ private URL createRepositoryURL(File file) {
+ try {
+ if (file.getName().endsWith(".link")) {
+ String path = getLinkPath(file);
+ // todo log
+ if (path == null)
+ return null;
+ file = new File(path);
+ if (!file.isAbsolute())
+ file = new File(file, path).getCanonicalFile();
+ }
+
+ URL repositoryURL = file.toURL();
+ if (file.getName().endsWith(".zip") || file.getName().endsWith(".jar")) {
+ repositoryURL = new URL("jar:" + repositoryURL.toString() + "!/");
+ }
+ return repositoryURL;
+ } catch (IOException e) {
+ // todo log
+ }
+ return null;
+ }
+
+ public void loadMetadataRepository(URL repoURL) {
+ try {
+ metadataRepositories.add(Activator.loadMetadataRepository(repoURL));
+ } catch (ProvisionException e) {
+ //TODO: log
+ // ignore
+ }
+ }
+
+ public void loadArtifactRepository(URL repoURL) {
+ try {
+ artifactRepositories.add(Activator.loadArtifactRepository(repoURL));
+ } catch (ProvisionException e) {
+ //TODO: log
+ // ignore
+ }
+ }
+
+ public void stopPoll() {
+
+ synchronizeDropinMetadataRepositories();
+ synchronizeDropinArtifactRepositories();
+
+ super.stopPoll();
+ }
+
+ private void synchronizeDropinMetadataRepositories() {
+ List currentRepositories = new ArrayList();
+ for (Iterator it = metadataRepositories.iterator(); it.hasNext();) {
+ IMetadataRepository repository = (IMetadataRepository) it.next();
+ String urlString = repository.getLocation().toExternalForm();
+ currentRepositories.add(urlString);
+ }
+ List previousRepositories = getListRepositoryProperty(getMetadataRepository(), DROPIN_METADATA_REPOSITORIES);
+ for (Iterator iterator = previousRepositories.iterator(); iterator.hasNext();) {
+ String repository = (String) iterator.next();
+ if (!currentRepositories.contains(repository))
+ removeMetadataRepository(repository);
+ }
+ setListRepositoryProperty(getMetadataRepository(), DROPIN_METADATA_REPOSITORIES, currentRepositories);
+ }
+
+ private void removeMetadataRepository(String urlString) {
+ ServiceReference reference = context.getServiceReference(IMetadataRepositoryManager.class.getName());
+ IMetadataRepositoryManager manager = null;
+ if (reference != null)
+ manager = (IMetadataRepositoryManager) context.getService(reference);
+ if (manager == null)
+ throw new IllegalStateException("MetadataRepositoryManager not registered.");
+
+ try {
+ manager.removeRepository(new URL(urlString));
+ } catch (MalformedURLException e) {
+ // TODO: log
+ // ignore
+ } finally {
+ context.ungetService(reference);
+ }
+ }
+
+ private void synchronizeDropinArtifactRepositories() {
+ List currentRepositories = new ArrayList();
+ for (Iterator it = artifactRepositories.iterator(); it.hasNext();) {
+ IArtifactRepository repository = (IArtifactRepository) it.next();
+ String urlString = repository.getLocation().toExternalForm();
+ currentRepositories.add(urlString);
+ }
+ List previousRepositories = getListRepositoryProperty(getArtifactRepository(), DROPIN_ARTIFACT_REPOSITORIES);
+ for (Iterator iterator = previousRepositories.iterator(); iterator.hasNext();) {
+ String repository = (String) iterator.next();
+ if (!currentRepositories.contains(repository))
+ removeArtifactRepository(repository);
+ }
+ setListRepositoryProperty(getArtifactRepository(), DROPIN_ARTIFACT_REPOSITORIES, currentRepositories);
+ }
+
+ public void removeArtifactRepository(String urlString) {
+ ServiceReference reference = context.getServiceReference(IArtifactRepositoryManager.class.getName());
+ IArtifactRepositoryManager manager = null;
+ if (reference != null)
+ manager = (IArtifactRepositoryManager) context.getService(reference);
+ if (manager == null)
+ throw new IllegalStateException("ArtifactRepositoryManager not registered.");
+
+ try {
+ manager.removeRepository(new URL(urlString));
+ } catch (MalformedURLException e) {
+ //TODO: log
+ // ignore
+ } finally {
+ context.ungetService(reference);
+ }
+ }
+
+ private List getListRepositoryProperty(IRepository repository, String key) {
+ List listProperty = new ArrayList();
+ String dropinRepositories = (String) repository.getProperties().get(key);
+ if (dropinRepositories != null) {
+ StringTokenizer tokenizer = new StringTokenizer(dropinRepositories, PIPE); //$NON-NLS-1$
+ while (tokenizer.hasMoreTokens()) {
+ listProperty.add(tokenizer.nextToken());
+ }
+ }
+ return listProperty;
+ }
+
+ private void setListRepositoryProperty(IRepository repository, String key, List listProperty) {
+ StringBuffer buffer = new StringBuffer();
+ for (Iterator it = listProperty.iterator(); it.hasNext();) {
+ String repositoryString = (String) it.next();
+ buffer.append(repositoryString);
+ if (it.hasNext())
+ buffer.append(PIPE);
+ }
+ String value = (buffer.length() == 0) ? null : buffer.toString();
+ repository.setProperty(key, value);
+ }
+
+ public IMetadataRepository[] getMetadataRepositories() {
+ List result = new ArrayList(metadataRepositories);
+ result.add(getMetadataRepository());
+ return (IMetadataRepository[]) result.toArray(new IMetadataRepository[0]);
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/LinksManager.java b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/LinksManager.java
deleted file mode 100644
index 4a494d2..0000000
--- a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/LinksManager.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008 IBM Corporation 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:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.equinox.internal.p2.reconciler.dropins;
-
-import java.io.*;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Iterator;
-import java.util.Properties;
-import org.eclipse.equinox.internal.p2.update.*;
-import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
-
-/**
- * @since 1.0
- */
-public class LinksManager {
-
- private static final String EXTENSION_LINK = ".link"; //$NON-NLS-1$
- private static final String PATH_PROPERTY = "path"; //$NON-NLS-1$
- private static final String PLATFORM_PROTOCOL = "platform:"; //$NON-NLS-1$
- private static final String ECLIPSE_FOLDER = "eclipse"; //$NON-NLS-1$
- private String defaultPolicy;
- private Configuration configuration;
- private boolean dirty = false;
-
- /*
- * If one site has a MANAGED_ONLY policy, then newly discovered sites must also have
- * the same thing. Otherwise, they will have a policy of USER_EXCLUDE.
- */
- private String getDefaultPolicy() {
- if (defaultPolicy == null) {
- for (Iterator iter = configuration.getSites().iterator(); defaultPolicy == null && iter.hasNext();) {
- if (Site.POLICY_MANAGED_ONLY.equals(((Site) iter.next()).getPolicy()))
- defaultPolicy = Site.POLICY_MANAGED_ONLY;
- }
- defaultPolicy = Site.POLICY_USER_EXCLUDE;
- }
- return defaultPolicy;
- }
-
- /*
- * Synchronize the given configuration file with the files that are in the specified links folder.
- * If any extension locations from the links folder are missing from the file, then update
- * the configuration.
- */
- public void synchronize(File configurationFile, File linksFolder) throws ProvisionException {
- if (!configurationFile.exists() || !linksFolder.exists())
- return;
-
- // read the existing configuration from disk
- configuration = ConfigurationParser.parse(configurationFile, null);
- if (configuration == null)
- return;
-
- // get the list of extension locations from the links folder
- linksFolder.listFiles(new FileFilter() {
- public boolean accept(File file) {
- if (file.isFile() && file.getName().endsWith(EXTENSION_LINK))
- configure(file);
- return false;
- }
- });
-
- // write out a new file if there were any changes.
- if (dirty)
- ConfigurationWriter.save(configuration, configurationFile, null);
- dirty = false;
- }
-
- /*
- * Roughly copied from PlatformConfiguration#configureExternalLinkSite in
- * Update Configurator.
- */
- void configure(File location) {
- String path = readExtension(location);
- boolean updateable = true;
-
- // parse out link information
- if (path.startsWith("r ")) { //$NON-NLS-1$
- updateable = false;
- path = path.substring(2).trim();
- } else if (path.startsWith("rw ")) { //$NON-NLS-1$
- path = path.substring(3).trim();
- } else {
- path = path.trim();
- }
-
- URL url;
- // make sure we have a valid link specification
- try {
- File siteFile = new File(path);
- siteFile = new File(siteFile, ECLIPSE_FOLDER);
- url = siteFile.toURL();
- if (findConfiguredSite(url) != null)
- // linked site is already known
- return;
- } catch (MalformedURLException e) {
- // ignore bad links ...
- e.printStackTrace();
- return;
- }
-
- Site site = new Site();
- site.setLinkFile(location.getAbsolutePath());
- site.setEnabled(true);
- site.setPolicy(getDefaultPolicy());
- site.setUpdateable(updateable);
- site.setUrl(url.toExternalForm());
- configuration.add(site);
- dirty = true;
- }
-
- /*
- * Look through the list of sites already known to this configuration
- * and determine if there is one with the given URL.
- */
- private Site findConfiguredSite(URL url) {
- String urlString = url.toExternalForm();
- Site result = internalFindConfiguredSite(urlString);
- if (result != null)
- return result;
- // try again with fixed URLs since they can be tricky
- try {
- urlString = Utils.decode(urlString, "UTF-8"); //$NON-NLS-1$
- } catch (UnsupportedEncodingException e) {
- // ignore
- }
- urlString = Utils.canonicalizeURL(urlString);
- return internalFindConfiguredSite(urlString);
- }
-
- private Site internalFindConfiguredSite(String url) {
- for (Iterator iter = configuration.getSites().iterator(); iter.hasNext();) {
- Site site = (Site) iter.next();
- String urlString = site.getUrl();
- urlString = Utils.canonicalizeURL(urlString);
- if (urlString.startsWith(PLATFORM_PROTOCOL))
- continue;
- if (urlString.equals(url))
- return site;
- }
- return null;
- }
-
- /*
- * Read the contents of a link file and return the path. May or may not include
- * a prefix indicating read-only or read-write status.
- */
- private String readExtension(File file) {
- Properties props = new Properties();
- InputStream input = null;
- try {
- input = new BufferedInputStream(new FileInputStream(file));
- props.load(input);
- } catch (IOException e) {
- // TODO
- e.printStackTrace();
- return null;
- } finally {
- if (input != null)
- try {
- input.close();
- } catch (IOException e) {
- // ignore
- }
- }
- return props.getProperty(PATH_PROPERTY);
- }
-}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/PlatformXmlListener.java b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/PlatformXmlListener.java
index 9597335..6359520 100644
--- a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/PlatformXmlListener.java
+++ b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/PlatformXmlListener.java
@@ -20,7 +20,7 @@
import org.eclipse.equinox.internal.p2.update.*;
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
import org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryChangeListener;
-import org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryWatcher;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
/**
* @since 1.0
@@ -101,7 +101,7 @@
added(delta.added());
removed(delta.removed());
changed(delta.changed());
- Activator.synchronize(getMetadataRepositories(), null); // TODO proper progress monitoring?
+ //Activator.synchronize(getMetadataRepositories(), null); // TODO proper progress monitoring?
}
// iterate over the site listeners and collect the metadata repositories
@@ -109,7 +109,7 @@
List result = new ArrayList();
for (Iterator iter = sites.values().iterator(); iter.hasNext();) {
SiteInfo info = (SiteInfo) iter.next();
- result.add(info.getListener().getMetadataRepository());
+ result.add(info.getRepository());
}
return result;
}
@@ -133,12 +133,11 @@
} catch (IOException e) {
throw new ProvisionException(Messages.errorProcessingConfg, e);
}
- File file = new File(url.getPath(), "plugins"); //$NON-NLS-1$
- DirectoryWatcher watcher = new DirectoryWatcher(file);
- SiteListener listener = new SiteListener(site);
- watcher.addListener(listener);
- watcher.poll();
- sites.put(site.getUrl(), new SiteInfo(site, watcher, listener));
+ IMetadataRepository repo = Activator.loadMetadataRepository(url);
+ if (repo == null) {
+ // todo
+ } else
+ sites.put(site.getUrl(), new SiteInfo(site, repo));
} catch (MalformedURLException e) {
throw new ProvisionException(Messages.errorProcessingConfg, e);
}
@@ -159,7 +158,7 @@
if (info == null) {
//
}
- info.getWatcher().stop();
+
sites.remove(site.getUrl());
}
}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/ProfileSynchronizer.java b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/ProfileSynchronizer.java
index 4cf256e..1088115 100644
--- a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/ProfileSynchronizer.java
+++ b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/ProfileSynchronizer.java
@@ -10,208 +10,217 @@
package org.eclipse.equinox.internal.p2.reconciler.dropins;
import java.io.IOException;
+import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
+import java.util.Map.Entry;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.provisional.configurator.Configurator;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IFileArtifactRepository;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
import org.eclipse.equinox.internal.provisional.p2.director.*;
import org.eclipse.equinox.internal.provisional.p2.engine.*;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.internal.provisional.p2.metadata.query.InstallableUnitQuery;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
import org.eclipse.equinox.internal.provisional.p2.query.Collector;
+import org.eclipse.equinox.internal.provisional.p2.query.Query;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
public class ProfileSynchronizer {
- private static final String FILE_LAST_MODIFIED = "file.lastModified"; //$NON-NLS-1$
- private static final String FILE_NAME = "file.name"; //$NON-NLS-1$
- private static final String REPOSITORY_ID = "repository.id"; //$NON-NLS-1$
- private IInstallableUnit[] iusToRemove;
- private IInstallableUnit[] iusToAdd;
- private IProfile profile;
- private List repositories;
+ public class ListCollector extends Collector {
+ public List getList() {
+ return super.getList();
+ }
+ }
+
+ private static final String SYNCH_REPOSITORY_ID = "synch.repository.id"; //$NON-NLS-1$
+ private static final String CACHE_EXTENSIONS = "org.eclipse.equinox.p2.cache.extensions"; //$NON-NLS-1$
+ private static final String PIPE = "|"; //$NON-NLS-1$
+ final IProfile profile;
+ final Map repositoryMap;
/*
* Constructor for the class.
*/
- public ProfileSynchronizer(IProfile profile, List repositories) {
- super();
+ public ProfileSynchronizer(IProfile profile, Collection repositories) {
this.profile = profile;
- this.repositories = repositories;
- initialize();
- }
-
- public void add(List additions) {
- this.repositories.addAll(repositories);
- initialize();
- // TODO progress monitoring
- synchronize(null);
- }
-
- /*
- * Initialize the synchronizer with default values.
- */
- private void initialize() {
- // snapshot is a table of all the IUs from this repository which are installed in the profile
- final Map snapshot = new HashMap();
- for (Iterator iter = repositories.iterator(); iter.hasNext();) {
- IMetadataRepository metadataRepository = (IMetadataRepository) iter.next();
- String repositoryId = metadataRepository.getLocation().toExternalForm();
- Iterator it = profile.query(InstallableUnitQuery.ANY, new Collector(), null).iterator();
- while (it.hasNext()) {
- IInstallableUnit iu = (IInstallableUnit) it.next();
- if (repositoryId.equals(iu.getProperty(REPOSITORY_ID))) {
- String fileName = iu.getProperty(FILE_NAME);
- if (fileName != null)
- snapshot.put(fileName, iu);
- }
- }
- }
-
- final List toAdd = new ArrayList();
- //create the collector that will visit all the IUs in the repositories being synchronized
- Collector syncCollector = new Collector() {
- public boolean accept(Object object) {
- IInstallableUnit iu = (IInstallableUnit) object;
- String iuFileName = iu.getProperty(FILE_NAME);
- // TODO is this right?
- if (iuFileName == null)
- return true;
-
- // if the repository contains an IU that the profile doesn't, then add it to the list to install
- IInstallableUnit profileIU = (IInstallableUnit) snapshot.get(iuFileName);
- if (profileIU == null) {
- toAdd.add(iu);
- return true;
- }
-
- Long iuLastModified = new Long(iu.getProperty(FILE_LAST_MODIFIED));
- Long profileIULastModified = new Long(profileIU.getProperty(FILE_LAST_MODIFIED));
- // TODO is this right?
- if (iuLastModified == null || profileIULastModified == null)
- return true;
-
- // if the timestamp hasn't changed, then there is nothing to do so remove
- // the IU from the snapshot so we don't accidentally remove it later
- if (iuLastModified.equals(profileIULastModified))
- snapshot.remove(iuFileName);
- else
- toAdd.add(iu);
- return true;
- }
- };
-
+ this.repositoryMap = new HashMap();
for (Iterator it = repositories.iterator(); it.hasNext();) {
- IMetadataRepository repo = (IMetadataRepository) it.next();
- // TODO report progress
- repo.query(InstallableUnitQuery.ANY, syncCollector, null);
- }
-
- // the IUs to remove is everything left that hasn't been removed from the snapshot
- if (!snapshot.isEmpty()) {
- iusToRemove = (IInstallableUnit[]) snapshot.values().toArray(new IInstallableUnit[snapshot.size()]);
- }
-
- // the list of IUs to add
- if (!toAdd.isEmpty()) {
- iusToAdd = (IInstallableUnit[]) toAdd.toArray(new IInstallableUnit[toAdd.size()]);
+ IMetadataRepository repository = (IMetadataRepository) it.next();
+ repositoryMap.put(repository.getLocation().toExternalForm(), repository);
}
}
/*
* Synchronize the profile with the list of metadata repositories.
*/
- public void synchronize(IProgressMonitor monitor) {
- IStatus status = Status.OK_STATUS;
- if (iusToRemove != null)
- status = removeIUs(iusToRemove, null); // TODO proper progress monitoring
- if (!status.isOK()) {
- // TODO
- throw new RuntimeException(new CoreException(status));
- }
+ public IStatus synchronize(IProgressMonitor monitor) {
- // disable repo cleanup for now until we see how we want to handle support for links folders and eclipse extensions
- //removeUnwatchedRepositories(context, profile, watchedFolder);
+ IStatus status = synchronizeCacheExtensions();
+ if (!status.isOK())
+ return status;
- if (iusToAdd != null)
- status = addIUs(iusToAdd, null); // TODO proper progress monitoring
- if (!status.isOK()) {
- // TODO
- throw new RuntimeException(new CoreException(status));
- }
- // if we did any work we have to apply the changes
- if (iusToAdd != null || iusToRemove != null)
- applyConfiguration();
- }
-
- /*
- * Install the given list of IUs.
- */
- private IStatus addIUs(IInstallableUnit[] toAdd, IProgressMonitor monitor) {
- BundleContext context = Activator.getContext();
+ ProfileChangeRequest request = createProfileChangeRequest();
+ if (request == null)
+ return Status.OK_STATUS;
SubMonitor sub = SubMonitor.convert(monitor, 100);
+ ProvisioningContext provisioningContext = new ProvisioningContext(new URL[0]);
- ServiceReference reference = context.getServiceReference(IPlanner.class.getName());
- IPlanner planner = (IPlanner) context.getService(reference);
+ ProvisioningPlan plan = createProvisioningPlan(request, provisioningContext, sub.newChild(50));
+ if (!plan.getStatus().isOK())
+ return plan.getStatus();
- try {
- ProfileChangeRequest request = new ProfileChangeRequest(profile);
- request.addInstallableUnits(toAdd);
- // mark the roots as such
- for (int i = 0; i < toAdd.length; i++) {
- if (Boolean.valueOf(toAdd[i].getProperty(IInstallableUnit.PROP_TYPE_GROUP)).booleanValue())
- request.setInstallableUnitProfileProperty(toAdd[i], IInstallableUnit.PROP_PROFILE_ROOT_IU, Boolean.toString(true));
+ if (plan.getOperands().length == 0) {
+ sub.done();
+ return Status.OK_STATUS;
+ }
+
+ status = executePlan(plan, provisioningContext, sub.newChild(50));
+ if (!status.isOK())
+ return status;
+
+ applyConfiguration();
+ return Status.OK_STATUS;
+ }
+
+ private IStatus synchronizeCacheExtensions() {
+ List currentExtensions = new ArrayList();
+ StringBuffer buffer = new StringBuffer();
+ for (Iterator it = repositoryMap.keySet().iterator(); it.hasNext();) {
+ String repositoryId = (String) it.next();
+ try {
+ IArtifactRepository repository = Activator.loadArtifactRepository(new URL(repositoryId));
+
+ if (repository instanceof IFileArtifactRepository) {
+ currentExtensions.add(repositoryId);
+ buffer.append(repositoryId);
+ if (it.hasNext())
+ buffer.append(PIPE);
+ }
+ } catch (ProvisionException e) {
+ // ignore
+ } catch (MalformedURLException e) {
+ // unexpected
+ e.printStackTrace();
}
-
- ProvisioningContext provisioningContext = new ProvisioningContext(new URL[0]);
- ProvisioningPlan plan = planner.getProvisioningPlan(request, provisioningContext, sub.newChild(50));
- if (!plan.getStatus().isOK())
- return plan.getStatus();
-
- return executePlan(plan, provisioningContext, sub.newChild(50));
-
- } finally {
- context.ungetService(reference);
}
+ String currentExtensionsProperty = (buffer.length() == 0) ? null : buffer.toString();
+
+ List previousExtensions = new ArrayList();
+ String previousExtensionsProperty = profile.getProperty(CACHE_EXTENSIONS);
+ if (previousExtensionsProperty != null) {
+ StringTokenizer tokenizer = new StringTokenizer(previousExtensionsProperty, PIPE);
+ while (tokenizer.hasMoreTokens()) {
+ previousExtensions.add(tokenizer.nextToken());
+ }
+ }
+
+ if (previousExtensions.size() == currentExtensions.size() && previousExtensions.containsAll(currentExtensions))
+ return Status.OK_STATUS;
+
+ Operand operand = new PropertyOperand(CACHE_EXTENSIONS, previousExtensionsProperty, currentExtensionsProperty);
+
+ return executeOperands(new ProvisioningContext(new URL[0]), new Operand[] {operand}, null);
}
- /*
- * Uninstall the given list of IUs.
- */
- private IStatus removeIUs(IInstallableUnit[] toRemove, IProgressMonitor monitor) {
+ private ProfileChangeRequest createProfileChangeRequest() {
+ boolean modified = false;
+ Collection profileIUs = getProfileIUs();
+ Collection toRemove = getStaleIUs();
+ profileIUs.removeAll(toRemove);
+
+ ProfileChangeRequest request = new ProfileChangeRequest(profile);
+ for (Iterator it = repositoryMap.entrySet().iterator(); it.hasNext();) {
+ Entry entry = (Entry) it.next();
+ String repositoryId = (String) entry.getKey();
+ IMetadataRepository repository = (IMetadataRepository) entry.getValue();
+ Iterator repositoryIterator = repository.query(InstallableUnitQuery.ANY, new Collector(), null).iterator();
+ while (repositoryIterator.hasNext()) {
+ IInstallableUnit iu = (IInstallableUnit) repositoryIterator.next();
+ if (profileIUs.contains(iu))
+ continue;
+
+ if (toRemove.contains(iu)) {
+ toRemove.remove(iu);
+ } else {
+ request.addInstallableUnits(new IInstallableUnit[] {iu});
+ if (Boolean.valueOf(iu.getProperty(IInstallableUnit.PROP_TYPE_GROUP)).booleanValue())
+ request.setInstallableUnitProfileProperty(iu, IInstallableUnit.PROP_PROFILE_ROOT_IU, Boolean.TRUE.toString());
+ }
+ request.setInstallableUnitProfileProperty(iu, SYNCH_REPOSITORY_ID, repositoryId);
+ profileIUs.add(iu);
+ modified = true;
+ }
+ }
+ if (!toRemove.isEmpty()) {
+ request.removeInstallableUnits((IInstallableUnit[]) toRemove.toArray(new IInstallableUnit[0]));
+ modified = true;
+ }
+
+ if (!modified)
+ return null;
+
+ return request;
+ }
+
+ private Collection getStaleIUs() {
+ Query removeQuery = new Query() {
+ public boolean isMatch(Object object) {
+ IInstallableUnit iu = (IInstallableUnit) object;
+ String repositoryId = profile.getInstallableUnitProperty(iu, SYNCH_REPOSITORY_ID);
+ if (repositoryId == null)
+ return false;
+
+ IMetadataRepository repo = (IMetadataRepository) repositoryMap.get(repositoryId);
+ Query iuQuery = new InstallableUnitQuery(iu.getId(), iu.getVersion());
+ return (repo == null || repo.query(iuQuery, new Collector(), null).isEmpty());
+ }
+ };
+
+ ListCollector listCollector = new ListCollector();
+ profile.query(removeQuery, listCollector, null);
+
+ List result = listCollector.getList();
+ return (result != null) ? result : Collections.EMPTY_LIST;
+ }
+
+ private List getProfileIUs() {
+ ListCollector listCollector = new ListCollector();
+ profile.query(InstallableUnitQuery.ANY, listCollector, null);
+
+ List result = listCollector.getList();
+ return (result != null) ? result : Collections.EMPTY_LIST;
+ }
+
+ private ProvisioningPlan createProvisioningPlan(ProfileChangeRequest request, ProvisioningContext provisioningContext, IProgressMonitor monitor) {
BundleContext context = Activator.getContext();
-
- SubMonitor sub = SubMonitor.convert(monitor, 100);
-
ServiceReference reference = context.getServiceReference(IPlanner.class.getName());
IPlanner planner = (IPlanner) context.getService(reference);
try {
- ProfileChangeRequest request = new ProfileChangeRequest(profile);
- request.removeInstallableUnits(toRemove);
-
- ProvisioningContext provisioningContext = new ProvisioningContext(new URL[0]);
- ProvisioningPlan plan = planner.getProvisioningPlan(request, provisioningContext, sub.newChild(50));
- if (!plan.getStatus().isOK())
- return plan.getStatus();
-
- return executePlan(plan, provisioningContext, sub.newChild(50));
-
+ return planner.getProvisioningPlan(request, provisioningContext, monitor);
} finally {
context.ungetService(reference);
}
}
private IStatus executePlan(ProvisioningPlan plan, ProvisioningContext provisioningContext, IProgressMonitor monitor) {
+ Operand[] operands = plan.getOperands();
+ return executeOperands(provisioningContext, operands, monitor);
+ }
+
+ private IStatus executeOperands(ProvisioningContext provisioningContext, Operand[] operands, IProgressMonitor monitor) {
BundleContext context = Activator.getContext();
ServiceReference reference = context.getServiceReference(IEngine.class.getName());
IEngine engine = (IEngine) context.getService(reference);
try {
PhaseSet phaseSet = new DefaultPhaseSet();
- IStatus engineResult = engine.perform(profile, phaseSet, plan.getOperands(), provisioningContext, monitor);
+ IStatus engineResult = engine.perform(profile, phaseSet, operands, provisioningContext, monitor);
return engineResult;
} finally {
context.ungetService(reference);
@@ -234,5 +243,4 @@
context.ungetService(reference);
}
}
-
}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/SiteInfo.java b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/SiteInfo.java
index e9c3e47..d891811 100644
--- a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/SiteInfo.java
+++ b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/SiteInfo.java
@@ -11,23 +11,21 @@
package org.eclipse.equinox.internal.p2.reconciler.dropins;
import org.eclipse.equinox.internal.p2.update.Site;
-import org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryWatcher;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
/*
* Internal class contains information about watchers and sites. Used for caching.
*/
public class SiteInfo {
- private DirectoryWatcher watcher;
- private SiteListener listener;
+ private IMetadataRepository repository;
private Site site;
private String url;
- public SiteInfo(Site site, DirectoryWatcher watcher, SiteListener listener) {
+ public SiteInfo(Site site, IMetadataRepository repository) {
super();
this.site = site;
this.url = site.getUrl();
- this.watcher = watcher;
- this.listener = listener;
+ this.repository = repository;
}
public Site getSite() {
@@ -38,12 +36,8 @@
return url;
}
- public DirectoryWatcher getWatcher() {
- return watcher;
- }
-
- public SiteListener getListener() {
- return listener;
+ public IMetadataRepository getRepository() {
+ return repository;
}
/* (non-Javadoc)
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/SiteListener.java b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/SiteListener.java
deleted file mode 100644
index f63e16b..0000000
--- a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/SiteListener.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2008 IBM Corporation 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:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.equinox.internal.p2.reconciler.dropins;
-
-import java.io.File;
-import org.eclipse.equinox.internal.p2.update.Site;
-import org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener;
-
-/**
- * @since 1.0
- */
-public class SiteListener extends RepositoryListener {
-
- private Site site;
-
- /*
- * Create a new site listener on the given site.
- */
- public SiteListener(Site site) {
- super(Activator.getContext(), Integer.toString(site.getUrl().hashCode()));
- this.site = site;
- }
-
- /*
- * Return true if the given list contains the symbolic name for the bundle
- * represented by the given file handle. Return false otherwise.
- */
- private boolean contains(String[] plugins, File file) {
- String filename = file.getAbsolutePath();
- for (int i = 0; i < plugins.length; i++)
- if (plugins[i].endsWith(filename))
- return true;
- return false;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryChangeListener#isInterested(java.io.File)
- */
- public boolean isInterested(File file) {
- String policy = site.getPolicy();
- String[] plugins = site.getList();
- if (Site.POLICY_MANAGED_ONLY.equals(policy)) {
- // TODO
- } else if (Site.POLICY_USER_EXCLUDE.equals(policy)) {
- // ensure the file doesn't refer to a plug-in in our list
- return plugins.length == 0 ? true : !contains(plugins, file);
- } else if (Site.POLICY_USER_INCLUDE.equals(policy)) {
- // we are only interested in plug-ins in the list
- return plugins.length == 0 ? false : contains(plugins, file);
- }
- return false;
- }
-}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.reconciler/META-INF/MANIFEST.MF
index 15e1965..3746432 100644
--- a/bundles/org.eclipse.equinox.p2.reconciler/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.reconciler/META-INF/MANIFEST.MF
@@ -6,7 +6,6 @@
Bundle-Localization: plugin
Bundle-Version: 0.1.0.qualifier
Bundle-Activator: org.eclipse.equinox.internal.p2.reconciler.dropins.Activator
-Eclipse-LazyStart: true
Bundle-RequiredExecutionEnvironment: J2SE-1.4,
CDC-1.1/Foundation-1.1
Import-Package: org.eclipse.equinox.internal.p2.update,
@@ -21,6 +20,9 @@
org.eclipse.equinox.internal.provisional.p2.metadata.query,
org.eclipse.equinox.internal.provisional.p2.metadata.repository,
org.eclipse.equinox.internal.provisional.p2.query,
+ org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository,
+ org.eclipse.equinox.internal.provisional.spi.p2.core.repository,
+ org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository,
org.eclipse.osgi.service.datalocation;version="1.0.0",
org.eclipse.osgi.util;version="1.1.0",
org.osgi.framework;version="1.3.0",
diff --git a/bundles/org.eclipse.equinox.p2.reconciler/build.properties b/bundles/org.eclipse.equinox.p2.reconciler/build.properties
index 97493b2..eb63c6e 100644
--- a/bundles/org.eclipse.equinox.p2.reconciler/build.properties
+++ b/bundles/org.eclipse.equinox.p2.reconciler/build.properties
@@ -13,4 +13,5 @@
bin.includes = META-INF/,\
.,\
plugin.properties,\
- about.html
+ about.html,\
+ plugin.xml
diff --git a/bundles/org.eclipse.equinox.p2.reconciler/plugin.xml b/bundles/org.eclipse.equinox.p2.reconciler/plugin.xml
new file mode 100644
index 0000000..81c2c8e
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.reconciler/plugin.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+ <extension
+ id="extensionRepository"
+ point="org.eclipse.equinox.p2.metadata.repository.metadataRepositories">
+ <factory
+ class="org.eclipse.equinox.internal.p2.extensionlocation.ExtensionLocationMetadataRepositoryFactory">
+ </factory>
+ <filter
+ suffix="eclipse">
+ </filter>
+ </extension>
+ <extension
+ point="org.eclipse.equinox.p2.artifact.repository.artifactRepositories">
+ <factory
+ class="org.eclipse.equinox.internal.p2.extensionlocation.ExtensionLocationArtifactRepositoryFactory">
+ </factory>
+ <filter
+ suffix="eclipse">
+ </filter>
+ </extension>
+</plugin>
diff --git a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepository.java b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepository.java
new file mode 100644
index 0000000..8d6581b
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepository.java
@@ -0,0 +1,151 @@
+package org.eclipse.equinox.internal.p2.extensionlocation;
+
+import java.io.File;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.reconciler.dropins.Activator;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.*;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
+import org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryWatcher;
+import org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener;
+import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey;
+import org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository.SimpleArtifactRepositoryFactory;
+import org.eclipse.equinox.internal.provisional.spi.p2.core.repository.AbstractRepository;
+import org.osgi.framework.BundleContext;
+
+public class ExtensionLocationArtifactRepository extends AbstractRepository implements IFileArtifactRepository {
+
+ //private static final String PROFILE_EXTENSION = "profile.extension"; //$NON-NLS-1$
+ private static final String ECLIPSE = "eclipse"; //$NON-NLS-1$
+ private static final String FEATURES = "features"; //$NON-NLS-1$
+ private static final String PLUGINS = "plugins"; //$NON-NLS-1$
+ private static final String FILE = "file"; //$NON-NLS-1$
+ private final IFileArtifactRepository artifactRepository;
+
+ public ExtensionLocationArtifactRepository(URL location, IProgressMonitor monitor) throws ProvisionException {
+ super("Extension: " + location.toExternalForm(), null, null, location, null, null); //$NON-NLS-1$
+
+ File base = getBaseDirectory(location);
+ File plugins = new File(base, PLUGINS);
+ File features = new File(base, FEATURES);
+
+ BundleContext context = Activator.getContext();
+ String stateDirName = Integer.toString(location.toExternalForm().hashCode());
+ File bundleData = context.getDataFile(null);
+ File stateDir = new File(bundleData, stateDirName);
+ URL localRepositoryURL;
+ try {
+ localRepositoryURL = stateDir.toURL();
+ } catch (MalformedURLException e) {
+ // unexpected
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, "Failed to create local repository", e)); //$NON-NLS-1$
+ }
+
+ artifactRepository = (IFileArtifactRepository) initializeArtifactRepository(localRepositoryURL, "extension location implementation - " + location.toExternalForm()); //$NON-NLS-1$
+
+ DirectoryWatcher watcher = new DirectoryWatcher(new File[] {plugins, features});
+ RepositoryListener listener = new RepositoryListener(context, null, artifactRepository);
+ watcher.addListener(listener);
+ watcher.poll();
+ }
+
+ private IArtifactRepository initializeArtifactRepository(URL stateDirURL, String repositoryName) {
+ SimpleArtifactRepositoryFactory factory = new SimpleArtifactRepositoryFactory();
+ try {
+ return factory.load(stateDirURL, null);
+
+ } catch (ProvisionException e) {
+ //fall through and create a new repository
+ }
+ IArtifactRepository repository = factory.create(stateDirURL, repositoryName, null);
+ //repository.setProperty(PROFILE_EXTENSION, "true");
+ return repository;
+ }
+
+ public static void validate(URL location, IProgressMonitor monitor) throws ProvisionException {
+ getBaseDirectory(location);
+ }
+
+ public static File getBaseDirectory(URL url) throws ProvisionException {
+ if (url.getProtocol() != FILE)
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, "location must use file protocol", null));
+
+ File base = new File(url.getPath());
+ if (!base.isDirectory())
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, "location not a directory", null));
+
+ if (isBaseDirectory(base))
+ return base;
+
+ File eclipseBase = new File(base, ECLIPSE);
+ if (isBaseDirectory(eclipseBase))
+ return eclipseBase;
+
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, "location is not an extension", null));
+ }
+
+ private static boolean isBaseDirectory(File base) {
+ File plugins = new File(base, PLUGINS);
+ File features = new File(base, FEATURES);
+
+ return plugins.isDirectory() || features.isDirectory();
+ }
+
+ public void addDescriptor(IArtifactDescriptor descriptor) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void addDescriptors(IArtifactDescriptor[] descriptors) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void removeAll() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void removeDescriptor(IArtifactDescriptor descriptor) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void removeDescriptor(IArtifactKey key) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean contains(IArtifactDescriptor descriptor) {
+ return artifactRepository.contains(descriptor);
+ }
+
+ public boolean contains(IArtifactKey key) {
+ return artifactRepository.contains(key);
+ }
+
+ public IStatus getArtifact(IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) {
+ return artifactRepository.getArtifact(descriptor, destination, monitor);
+ }
+
+ public IArtifactDescriptor[] getArtifactDescriptors(IArtifactKey key) {
+ return artifactRepository.getArtifactDescriptors(key);
+ }
+
+ public IArtifactKey[] getArtifactKeys() {
+ return artifactRepository.getArtifactKeys();
+ }
+
+ public IStatus getArtifacts(IArtifactRequest[] requests, IProgressMonitor monitor) {
+ return artifactRepository.getArtifacts(requests, monitor);
+ }
+
+ public OutputStream getOutputStream(IArtifactDescriptor descriptor) throws ProvisionException {
+ return artifactRepository.getOutputStream(descriptor);
+ }
+
+ public File getArtifactFile(IArtifactKey key) {
+ return artifactRepository.getArtifactFile(key);
+ }
+
+ public File getArtifactFile(IArtifactDescriptor descriptor) {
+ return artifactRepository.getArtifactFile(descriptor);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepositoryFactory.java b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepositoryFactory.java
new file mode 100644
index 0000000..83cb924
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepositoryFactory.java
@@ -0,0 +1,28 @@
+package org.eclipse.equinox.internal.p2.extensionlocation;
+
+import java.net.URL;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
+import org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository.IArtifactRepositoryFactory;
+
+public class ExtensionLocationArtifactRepositoryFactory implements IArtifactRepositoryFactory {
+
+ public IArtifactRepository create(URL location, String name, String type) throws ProvisionException {
+ return null;
+ }
+
+ public IArtifactRepository load(URL location, IProgressMonitor monitor) throws ProvisionException {
+ return new ExtensionLocationArtifactRepository(location, monitor);
+ }
+
+ public IStatus validate(URL location, IProgressMonitor monitor) {
+ try {
+ ExtensionLocationArtifactRepository.validate(location, monitor);
+ } catch (ProvisionException e) {
+ return e.getStatus();
+ }
+ return Status.OK_STATUS;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepository.java b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepository.java
new file mode 100644
index 0000000..8004e2d
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepository.java
@@ -0,0 +1,108 @@
+package org.eclipse.equinox.internal.p2.extensionlocation;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.reconciler.dropins.Activator;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
+import org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryWatcher;
+import org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener;
+import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
+import org.eclipse.equinox.internal.provisional.p2.query.Collector;
+import org.eclipse.equinox.internal.provisional.p2.query.Query;
+import org.eclipse.equinox.internal.provisional.spi.p2.core.repository.AbstractRepository;
+import org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.SimpleMetadataRepositoryFactory;
+import org.osgi.framework.BundleContext;
+
+public class ExtensionLocationMetadataRepository extends AbstractRepository implements IMetadataRepository {
+
+ private static final String ECLIPSE = "eclipse"; //$NON-NLS-1$
+ private static final String FEATURES = "features"; //$NON-NLS-1$
+ private static final String PLUGINS = "plugins"; //$NON-NLS-1$
+ private static final String FILE = "file"; //$NON-NLS-1$
+ private final IMetadataRepository metadataRepository;
+
+ public ExtensionLocationMetadataRepository(URL location, IProgressMonitor monitor) throws ProvisionException {
+ super("Extension: " + location.toExternalForm(), null, null, location, null, null); //$NON-NLS-1$
+
+ File base = getBaseDirectory(location);
+ File plugins = new File(base, PLUGINS);
+ File features = new File(base, FEATURES);
+
+ BundleContext context = Activator.getContext();
+ String stateDirName = Integer.toString(location.toExternalForm().hashCode());
+ File bundleData = context.getDataFile(null);
+ File stateDir = new File(bundleData, stateDirName);
+ URL localRepositoryURL;
+ try {
+ localRepositoryURL = stateDir.toURL();
+ } catch (MalformedURLException e) {
+ // unexpected
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, "Failed to create local repository", e)); //$NON-NLS-1$
+ }
+
+ metadataRepository = initializeMetadataRepository(localRepositoryURL, "extension location implementation - " + location.toExternalForm()); //$NON-NLS-1$
+
+ DirectoryWatcher watcher = new DirectoryWatcher(new File[] {plugins, features});
+ RepositoryListener listener = new RepositoryListener(context, metadataRepository, null);
+ watcher.addListener(listener);
+ watcher.poll();
+ }
+
+ private IMetadataRepository initializeMetadataRepository(URL stateDirURL, String repositoryName) {
+ SimpleMetadataRepositoryFactory factory = new SimpleMetadataRepositoryFactory();
+ try {
+ return factory.load(stateDirURL, null);
+ } catch (ProvisionException e) {
+ //fall through and create a new repository
+ }
+ return factory.create(stateDirURL, repositoryName, null);
+ }
+
+ public void addInstallableUnits(IInstallableUnit[] installableUnits) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void removeAll() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean removeInstallableUnits(Query query, IProgressMonitor monitor) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Collector query(Query query, Collector collector, IProgressMonitor monitor) {
+ return metadataRepository.query(query, collector, monitor);
+ }
+
+ public static void validate(URL location, IProgressMonitor monitor) throws ProvisionException {
+ getBaseDirectory(location);
+ }
+
+ public static File getBaseDirectory(URL url) throws ProvisionException {
+ if (url.getProtocol() != FILE)
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, "location must use file protocol", null));
+
+ File base = new File(url.getPath());
+ if (!base.isDirectory())
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, "location not a directory", null));
+
+ if (isBaseDirectory(base))
+ return base;
+
+ File eclipseBase = new File(base, ECLIPSE);
+ if (isBaseDirectory(eclipseBase))
+ return eclipseBase;
+
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, "location is not an extension", null));
+ }
+
+ private static boolean isBaseDirectory(File base) {
+ File plugins = new File(base, PLUGINS);
+ File features = new File(base, FEATURES);
+
+ return plugins.isDirectory() || features.isDirectory();
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepositoryFactory.java b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepositoryFactory.java
new file mode 100644
index 0000000..31da09c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepositoryFactory.java
@@ -0,0 +1,28 @@
+package org.eclipse.equinox.internal.p2.extensionlocation;
+
+import java.net.URL;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
+import org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.IMetadataRepositoryFactory;
+
+public class ExtensionLocationMetadataRepositoryFactory implements IMetadataRepositoryFactory {
+
+ public IMetadataRepository create(URL location, String name, String type) throws ProvisionException {
+ return null;
+ }
+
+ public IMetadataRepository load(URL location, IProgressMonitor monitor) throws ProvisionException {
+ return new ExtensionLocationMetadataRepository(location, monitor);
+ }
+
+ public IStatus validate(URL location, IProgressMonitor monitor) {
+ try {
+ ExtensionLocationMetadataRepository.validate(location, monitor);
+ } catch (ProvisionException e) {
+ return e.getStatus();
+ }
+ return Status.OK_STATUS;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/Activator.java b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/Activator.java
index 1a46573..bddfb05 100644
--- a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/Activator.java
+++ b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/Activator.java
@@ -14,26 +14,75 @@
import java.net.URL;
import java.util.*;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepositoryManager;
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
import org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryWatcher;
-import org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener;
import org.eclipse.equinox.internal.provisional.p2.engine.IProfile;
import org.eclipse.equinox.internal.provisional.p2.engine.IProfileRegistry;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
import org.osgi.framework.*;
import org.osgi.service.packageadmin.PackageAdmin;
public class Activator implements BundleActivator {
+ public static final String ID = "org.eclipse.equinox.p2.reconciler.dropins"; //$NON-NLS-1$
private static final String DROPINS_DIRECTORY = "org.eclipse.equinox.p2.reconciler.dropins.directory"; //$NON-NLS-1$
private static final String OSGI_CONFIGURATION_AREA = "osgi.configuration.area"; //$NON-NLS-1$
private static final String DROPINS = "dropins"; //$NON-NLS-1$
- private static final String PROFILE_EXTENSION = "profile.extension"; //$NON-NLS-1$
+ // private static final String PROFILE_EXTENSION = "profile.extension"; //$NON-NLS-1$
private static PackageAdmin packageAdmin;
private static BundleContext bundleContext;
private ServiceReference packageAdminRef;
private List watchers = new ArrayList();
- private static IMetadataRepository dropinRepository;
+ private static IMetadataRepository[] dropinRepositories;
+ private static IMetadataRepository[] configurationRepositories;
+ private static IMetadataRepository[] linksRepositories;
+
+ /**
+ * Helper method to load a metadata repository from the specified URL.
+ * This method never returns <code>null</code>.
+ *
+ * @throws IllegalStateException
+ * @throws ProvisionException
+ */
+ public static IMetadataRepository loadMetadataRepository(URL repoURL) throws ProvisionException {
+ BundleContext context = getContext();
+ ServiceReference reference = context.getServiceReference(IMetadataRepositoryManager.class.getName());
+ IMetadataRepositoryManager manager = null;
+ if (reference != null)
+ manager = (IMetadataRepositoryManager) context.getService(reference);
+ if (manager == null)
+ throw new IllegalStateException("MetadataRepositoryManager not registered.");
+ try {
+ return manager.loadRepository(repoURL, null);
+ } finally {
+ context.ungetService(reference);
+ }
+ }
+
+ /**
+ * Helper method to load an artifact repository from the given URL.
+ * This method never returns <code>null</code>.
+ *
+ * @throws IllegalStateException
+ * @throws ProvisionException
+ */
+ public static IArtifactRepository loadArtifactRepository(URL repoURL) throws ProvisionException {
+ BundleContext context = getContext();
+ ServiceReference reference = context.getServiceReference(IArtifactRepositoryManager.class.getName());
+ IArtifactRepositoryManager manager = null;
+ if (reference != null)
+ manager = (IArtifactRepositoryManager) context.getService(reference);
+ if (manager == null)
+ throw new IllegalStateException("ArtifactRepositoryManager not registered.");
+ try {
+ return manager.loadRepository(repoURL, null);
+ } finally {
+ context.ungetService(reference);
+ }
+ }
/* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
@@ -55,9 +104,9 @@
// create the watcher for the "drop-ins" folder
watchDropins(profile);
-
- // create watchers for the sites specified in the platform.xml
- watchConfiguration();
+ // keep an eye on the platform.xml
+ if (false)
+ watchConfiguration();
synchronize(new ArrayList(0), null);
}
@@ -73,14 +122,21 @@
/*
* Synchronize the profile.
*/
- public static void synchronize(List extraRepositories, IProgressMonitor monitor) {
+ public static synchronized void synchronize(List extraRepositories, IProgressMonitor monitor) {
IProfile profile = getCurrentProfile(bundleContext);
if (profile == null)
return;
// create the profile synchronizer on all available repositories
- List repositories = new ArrayList(extraRepositories);
- if (dropinRepository != null)
- repositories.add(dropinRepository);
+ Set repositories = new HashSet(extraRepositories);
+ if (dropinRepositories != null)
+ repositories.addAll(Arrays.asList(dropinRepositories));
+
+ if (configurationRepositories != null)
+ repositories.addAll(Arrays.asList(configurationRepositories));
+
+ if (linksRepositories != null)
+ repositories.addAll(Arrays.asList(linksRepositories));
+
ProfileSynchronizer synchronizer = new ProfileSynchronizer(profile, repositories);
synchronizer.synchronize(monitor);
}
@@ -88,50 +144,43 @@
/*
* Watch the platform.xml file.
*/
- private void watchConfiguration() throws ProvisionException {
+ private void watchConfiguration() {
File configFile = new File("configuration/org.eclipse.update/platform.xml"); //$NON-NLS-1$
DirectoryWatcher watcher = new DirectoryWatcher(configFile.getParentFile());
try {
PlatformXmlListener listener = new PlatformXmlListener(configFile);
watcher.addListener(listener);
+ watcher.poll();
+ List repositories = listener.getMetadataRepositories();
+ if (repositories != null)
+ configurationRepositories = (IMetadataRepository[]) repositories.toArray(new IMetadataRepository[0]);
} catch (ProvisionException e) {
// TODO proper logging
e.printStackTrace();
}
- watchers.add(watcher);
- watcher.start();
-
- // pay attention to the links/ folder too. this is only needed on startup though since
- // any other changes during execution will be reflected in the platform.xml file
- LinksManager manager = new LinksManager();
- manager.synchronize(configFile, new File("links"));
}
/*
* Create a new directory watcher with a repository listener on the drop-ins folder.
*/
private void watchDropins(IProfile profile) {
- File folder = getWatchedDirectory(bundleContext);
- if (folder == null)
+ List directories = new ArrayList();
+ File dropinsDirectory = getDropinsDirectory();
+ if (dropinsDirectory != null)
+ directories.add(dropinsDirectory);
+ File linksDirectory = getLinksDirectory();
+ if (linksDirectory != null)
+ directories.add(linksDirectory);
+ if (directories.isEmpty())
return;
- RepositoryListener listener = new RepositoryListener(Activator.getContext(), Integer.toString(folder.hashCode()));
- listener.getArtifactRepository().setProperty(PROFILE_EXTENSION, profile.getProfileId());
-
- List folders = new ArrayList();
- folders.add(folder);
- File eclipseFeatures = new File(folder, "eclipse/features");
- if (eclipseFeatures.isDirectory())
- folders.add(eclipseFeatures);
- File eclipsePlugins = new File(folder, "eclipse/plugins");
- if (eclipsePlugins.isDirectory())
- folders.add(eclipsePlugins);
-
- DirectoryWatcher watcher = new DirectoryWatcher((File[]) folders.toArray(new File[folders.size()]));
+ DropinsRepositoryListener listener = new DropinsRepositoryListener(Activator.getContext(), "dropins:" + dropinsDirectory.getAbsolutePath());
+ // listener.getArtifactRepository().setProperty(PROFILE_EXTENSION, profile.getProfileId());
+ DirectoryWatcher watcher = new DirectoryWatcher((File[]) directories.toArray(new File[directories.size()]));
watcher.addListener(listener);
watcher.poll();
- dropinRepository = listener.getMetadataRepository();
+ dropinRepositories = listener.getMetadataRepositories();
}
/* (non-Javadoc)
@@ -154,15 +203,27 @@
return bundleContext;
}
- public static File getWatchedDirectory(BundleContext context) {
- String watchedDirectoryProperty = context.getProperty(DROPINS_DIRECTORY);
+ private static File getLinksDirectory() {
+ try {
+ //TODO: a proper install area would be better. osgi.install.area is relative to the framework jar
+ URL baseURL = new URL(bundleContext.getProperty(OSGI_CONFIGURATION_AREA));
+ URL folderURL = new URL(baseURL, "../links"); //$NON-NLS-1$
+ return new File(folderURL.getPath());
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static File getDropinsDirectory() {
+ String watchedDirectoryProperty = bundleContext.getProperty(DROPINS_DIRECTORY);
if (watchedDirectoryProperty != null) {
File folder = new File(watchedDirectoryProperty);
return folder;
}
try {
//TODO: a proper install area would be better. osgi.install.area is relative to the framework jar
- URL baseURL = new URL(context.getProperty(OSGI_CONFIGURATION_AREA));
+ URL baseURL = new URL(bundleContext.getProperty(OSGI_CONFIGURATION_AREA));
URL folderURL = new URL(baseURL, "../" + DROPINS); //$NON-NLS-1$
File folder = new File(folderURL.getPath());
return folder;
diff --git a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/DropinsRepositoryListener.java b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/DropinsRepositoryListener.java
new file mode 100644
index 0000000..9c4ce05
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/DropinsRepositoryListener.java
@@ -0,0 +1,239 @@
+package org.eclipse.equinox.internal.p2.reconciler.dropins;
+
+import java.io.*;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepositoryManager;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
+import org.eclipse.equinox.internal.provisional.p2.core.repository.IRepository;
+import org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public class DropinsRepositoryListener extends RepositoryListener {
+
+ private static final String DROPIN_ARTIFACT_REPOSITORIES = "dropin.artifactRepositories"; //$NON-NLS-1$
+ private static final String DROPIN_METADATA_REPOSITORIES = "dropin.metadataRepositories"; //$NON-NLS-1$
+ private static final String PIPE = "|"; //$NON-NLS-1$
+ private BundleContext context;
+ private List metadataRepositories = new ArrayList();
+ private List artifactRepositories = new ArrayList();
+
+ public DropinsRepositoryListener(BundleContext context, String repositoryName) {
+ super(context, repositoryName);
+ this.context = context;
+ }
+
+ public boolean isInterested(File file) {
+ if (file.isDirectory())
+ return true;
+
+ String name = file.getName();
+ return name.endsWith(".jar") || name.endsWith(".zip") || name.endsWith(".link");
+ }
+
+ public boolean added(File file) {
+ if (super.isInterested(file))
+ return super.added(file);
+
+ URL repositoryURL = createRepositoryURL(file);
+ if (repositoryURL != null) {
+ loadMetadataRepository(repositoryURL);
+ loadArtifactRepository(repositoryURL);
+ }
+ return true;
+ }
+
+ public boolean changed(File file) {
+ if (super.isInterested(file))
+ return super.added(file);
+
+ URL repositoryURL = createRepositoryURL(file);
+ if (repositoryURL != null) {
+ loadMetadataRepository(repositoryURL);
+ loadArtifactRepository(repositoryURL);
+ }
+ return true;
+ }
+
+ private String getLinkPath(File file) {
+ Properties links = new Properties();
+ try {
+ InputStream input = new BufferedInputStream(new FileInputStream(file));
+ try {
+ links.load(input);
+ } finally {
+ input.close();
+ }
+ } catch (IOException e) {
+ // ignore
+ }
+ String path = links.getProperty("path");
+ if (path == null) {
+ // log
+ return null;
+ }
+
+ // parse out link information
+ if (path.startsWith("r ")) { //$NON-NLS-1$
+ path = path.substring(2).trim();
+ } else if (path.startsWith("rw ")) { //$NON-NLS-1$
+ path = path.substring(3).trim();
+ } else {
+ path = path.trim();
+ }
+ return path;
+ }
+
+ private URL createRepositoryURL(File file) {
+ try {
+ if (file.getName().endsWith(".link")) {
+ String path = getLinkPath(file);
+ // todo log
+ if (path == null)
+ return null;
+ file = new File(path);
+ if (!file.isAbsolute())
+ file = new File(file, path).getCanonicalFile();
+ }
+
+ URL repositoryURL = file.toURL();
+ if (file.getName().endsWith(".zip") || file.getName().endsWith(".jar")) {
+ repositoryURL = new URL("jar:" + repositoryURL.toString() + "!/");
+ }
+ return repositoryURL;
+ } catch (IOException e) {
+ // todo log
+ }
+ return null;
+ }
+
+ public void loadMetadataRepository(URL repoURL) {
+ try {
+ metadataRepositories.add(Activator.loadMetadataRepository(repoURL));
+ } catch (ProvisionException e) {
+ //TODO: log
+ // ignore
+ }
+ }
+
+ public void loadArtifactRepository(URL repoURL) {
+ try {
+ artifactRepositories.add(Activator.loadArtifactRepository(repoURL));
+ } catch (ProvisionException e) {
+ //TODO: log
+ // ignore
+ }
+ }
+
+ public void stopPoll() {
+
+ synchronizeDropinMetadataRepositories();
+ synchronizeDropinArtifactRepositories();
+
+ super.stopPoll();
+ }
+
+ private void synchronizeDropinMetadataRepositories() {
+ List currentRepositories = new ArrayList();
+ for (Iterator it = metadataRepositories.iterator(); it.hasNext();) {
+ IMetadataRepository repository = (IMetadataRepository) it.next();
+ String urlString = repository.getLocation().toExternalForm();
+ currentRepositories.add(urlString);
+ }
+ List previousRepositories = getListRepositoryProperty(getMetadataRepository(), DROPIN_METADATA_REPOSITORIES);
+ for (Iterator iterator = previousRepositories.iterator(); iterator.hasNext();) {
+ String repository = (String) iterator.next();
+ if (!currentRepositories.contains(repository))
+ removeMetadataRepository(repository);
+ }
+ setListRepositoryProperty(getMetadataRepository(), DROPIN_METADATA_REPOSITORIES, currentRepositories);
+ }
+
+ private void removeMetadataRepository(String urlString) {
+ ServiceReference reference = context.getServiceReference(IMetadataRepositoryManager.class.getName());
+ IMetadataRepositoryManager manager = null;
+ if (reference != null)
+ manager = (IMetadataRepositoryManager) context.getService(reference);
+ if (manager == null)
+ throw new IllegalStateException("MetadataRepositoryManager not registered.");
+
+ try {
+ manager.removeRepository(new URL(urlString));
+ } catch (MalformedURLException e) {
+ // TODO: log
+ // ignore
+ } finally {
+ context.ungetService(reference);
+ }
+ }
+
+ private void synchronizeDropinArtifactRepositories() {
+ List currentRepositories = new ArrayList();
+ for (Iterator it = artifactRepositories.iterator(); it.hasNext();) {
+ IArtifactRepository repository = (IArtifactRepository) it.next();
+ String urlString = repository.getLocation().toExternalForm();
+ currentRepositories.add(urlString);
+ }
+ List previousRepositories = getListRepositoryProperty(getArtifactRepository(), DROPIN_ARTIFACT_REPOSITORIES);
+ for (Iterator iterator = previousRepositories.iterator(); iterator.hasNext();) {
+ String repository = (String) iterator.next();
+ if (!currentRepositories.contains(repository))
+ removeArtifactRepository(repository);
+ }
+ setListRepositoryProperty(getArtifactRepository(), DROPIN_ARTIFACT_REPOSITORIES, currentRepositories);
+ }
+
+ public void removeArtifactRepository(String urlString) {
+ ServiceReference reference = context.getServiceReference(IArtifactRepositoryManager.class.getName());
+ IArtifactRepositoryManager manager = null;
+ if (reference != null)
+ manager = (IArtifactRepositoryManager) context.getService(reference);
+ if (manager == null)
+ throw new IllegalStateException("ArtifactRepositoryManager not registered.");
+
+ try {
+ manager.removeRepository(new URL(urlString));
+ } catch (MalformedURLException e) {
+ //TODO: log
+ // ignore
+ } finally {
+ context.ungetService(reference);
+ }
+ }
+
+ private List getListRepositoryProperty(IRepository repository, String key) {
+ List listProperty = new ArrayList();
+ String dropinRepositories = (String) repository.getProperties().get(key);
+ if (dropinRepositories != null) {
+ StringTokenizer tokenizer = new StringTokenizer(dropinRepositories, PIPE); //$NON-NLS-1$
+ while (tokenizer.hasMoreTokens()) {
+ listProperty.add(tokenizer.nextToken());
+ }
+ }
+ return listProperty;
+ }
+
+ private void setListRepositoryProperty(IRepository repository, String key, List listProperty) {
+ StringBuffer buffer = new StringBuffer();
+ for (Iterator it = listProperty.iterator(); it.hasNext();) {
+ String repositoryString = (String) it.next();
+ buffer.append(repositoryString);
+ if (it.hasNext())
+ buffer.append(PIPE);
+ }
+ String value = (buffer.length() == 0) ? null : buffer.toString();
+ repository.setProperty(key, value);
+ }
+
+ public IMetadataRepository[] getMetadataRepositories() {
+ List result = new ArrayList(metadataRepositories);
+ result.add(getMetadataRepository());
+ return (IMetadataRepository[]) result.toArray(new IMetadataRepository[0]);
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/LinksManager.java b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/LinksManager.java
deleted file mode 100644
index 4a494d2..0000000
--- a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/LinksManager.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008 IBM Corporation 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:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.equinox.internal.p2.reconciler.dropins;
-
-import java.io.*;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Iterator;
-import java.util.Properties;
-import org.eclipse.equinox.internal.p2.update.*;
-import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
-
-/**
- * @since 1.0
- */
-public class LinksManager {
-
- private static final String EXTENSION_LINK = ".link"; //$NON-NLS-1$
- private static final String PATH_PROPERTY = "path"; //$NON-NLS-1$
- private static final String PLATFORM_PROTOCOL = "platform:"; //$NON-NLS-1$
- private static final String ECLIPSE_FOLDER = "eclipse"; //$NON-NLS-1$
- private String defaultPolicy;
- private Configuration configuration;
- private boolean dirty = false;
-
- /*
- * If one site has a MANAGED_ONLY policy, then newly discovered sites must also have
- * the same thing. Otherwise, they will have a policy of USER_EXCLUDE.
- */
- private String getDefaultPolicy() {
- if (defaultPolicy == null) {
- for (Iterator iter = configuration.getSites().iterator(); defaultPolicy == null && iter.hasNext();) {
- if (Site.POLICY_MANAGED_ONLY.equals(((Site) iter.next()).getPolicy()))
- defaultPolicy = Site.POLICY_MANAGED_ONLY;
- }
- defaultPolicy = Site.POLICY_USER_EXCLUDE;
- }
- return defaultPolicy;
- }
-
- /*
- * Synchronize the given configuration file with the files that are in the specified links folder.
- * If any extension locations from the links folder are missing from the file, then update
- * the configuration.
- */
- public void synchronize(File configurationFile, File linksFolder) throws ProvisionException {
- if (!configurationFile.exists() || !linksFolder.exists())
- return;
-
- // read the existing configuration from disk
- configuration = ConfigurationParser.parse(configurationFile, null);
- if (configuration == null)
- return;
-
- // get the list of extension locations from the links folder
- linksFolder.listFiles(new FileFilter() {
- public boolean accept(File file) {
- if (file.isFile() && file.getName().endsWith(EXTENSION_LINK))
- configure(file);
- return false;
- }
- });
-
- // write out a new file if there were any changes.
- if (dirty)
- ConfigurationWriter.save(configuration, configurationFile, null);
- dirty = false;
- }
-
- /*
- * Roughly copied from PlatformConfiguration#configureExternalLinkSite in
- * Update Configurator.
- */
- void configure(File location) {
- String path = readExtension(location);
- boolean updateable = true;
-
- // parse out link information
- if (path.startsWith("r ")) { //$NON-NLS-1$
- updateable = false;
- path = path.substring(2).trim();
- } else if (path.startsWith("rw ")) { //$NON-NLS-1$
- path = path.substring(3).trim();
- } else {
- path = path.trim();
- }
-
- URL url;
- // make sure we have a valid link specification
- try {
- File siteFile = new File(path);
- siteFile = new File(siteFile, ECLIPSE_FOLDER);
- url = siteFile.toURL();
- if (findConfiguredSite(url) != null)
- // linked site is already known
- return;
- } catch (MalformedURLException e) {
- // ignore bad links ...
- e.printStackTrace();
- return;
- }
-
- Site site = new Site();
- site.setLinkFile(location.getAbsolutePath());
- site.setEnabled(true);
- site.setPolicy(getDefaultPolicy());
- site.setUpdateable(updateable);
- site.setUrl(url.toExternalForm());
- configuration.add(site);
- dirty = true;
- }
-
- /*
- * Look through the list of sites already known to this configuration
- * and determine if there is one with the given URL.
- */
- private Site findConfiguredSite(URL url) {
- String urlString = url.toExternalForm();
- Site result = internalFindConfiguredSite(urlString);
- if (result != null)
- return result;
- // try again with fixed URLs since they can be tricky
- try {
- urlString = Utils.decode(urlString, "UTF-8"); //$NON-NLS-1$
- } catch (UnsupportedEncodingException e) {
- // ignore
- }
- urlString = Utils.canonicalizeURL(urlString);
- return internalFindConfiguredSite(urlString);
- }
-
- private Site internalFindConfiguredSite(String url) {
- for (Iterator iter = configuration.getSites().iterator(); iter.hasNext();) {
- Site site = (Site) iter.next();
- String urlString = site.getUrl();
- urlString = Utils.canonicalizeURL(urlString);
- if (urlString.startsWith(PLATFORM_PROTOCOL))
- continue;
- if (urlString.equals(url))
- return site;
- }
- return null;
- }
-
- /*
- * Read the contents of a link file and return the path. May or may not include
- * a prefix indicating read-only or read-write status.
- */
- private String readExtension(File file) {
- Properties props = new Properties();
- InputStream input = null;
- try {
- input = new BufferedInputStream(new FileInputStream(file));
- props.load(input);
- } catch (IOException e) {
- // TODO
- e.printStackTrace();
- return null;
- } finally {
- if (input != null)
- try {
- input.close();
- } catch (IOException e) {
- // ignore
- }
- }
- return props.getProperty(PATH_PROPERTY);
- }
-}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/PlatformXmlListener.java b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/PlatformXmlListener.java
index 9597335..6359520 100644
--- a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/PlatformXmlListener.java
+++ b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/PlatformXmlListener.java
@@ -20,7 +20,7 @@
import org.eclipse.equinox.internal.p2.update.*;
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
import org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryChangeListener;
-import org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryWatcher;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
/**
* @since 1.0
@@ -101,7 +101,7 @@
added(delta.added());
removed(delta.removed());
changed(delta.changed());
- Activator.synchronize(getMetadataRepositories(), null); // TODO proper progress monitoring?
+ //Activator.synchronize(getMetadataRepositories(), null); // TODO proper progress monitoring?
}
// iterate over the site listeners and collect the metadata repositories
@@ -109,7 +109,7 @@
List result = new ArrayList();
for (Iterator iter = sites.values().iterator(); iter.hasNext();) {
SiteInfo info = (SiteInfo) iter.next();
- result.add(info.getListener().getMetadataRepository());
+ result.add(info.getRepository());
}
return result;
}
@@ -133,12 +133,11 @@
} catch (IOException e) {
throw new ProvisionException(Messages.errorProcessingConfg, e);
}
- File file = new File(url.getPath(), "plugins"); //$NON-NLS-1$
- DirectoryWatcher watcher = new DirectoryWatcher(file);
- SiteListener listener = new SiteListener(site);
- watcher.addListener(listener);
- watcher.poll();
- sites.put(site.getUrl(), new SiteInfo(site, watcher, listener));
+ IMetadataRepository repo = Activator.loadMetadataRepository(url);
+ if (repo == null) {
+ // todo
+ } else
+ sites.put(site.getUrl(), new SiteInfo(site, repo));
} catch (MalformedURLException e) {
throw new ProvisionException(Messages.errorProcessingConfg, e);
}
@@ -159,7 +158,7 @@
if (info == null) {
//
}
- info.getWatcher().stop();
+
sites.remove(site.getUrl());
}
}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/ProfileSynchronizer.java b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/ProfileSynchronizer.java
index 4cf256e..1088115 100644
--- a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/ProfileSynchronizer.java
+++ b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/ProfileSynchronizer.java
@@ -10,208 +10,217 @@
package org.eclipse.equinox.internal.p2.reconciler.dropins;
import java.io.IOException;
+import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
+import java.util.Map.Entry;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.provisional.configurator.Configurator;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IFileArtifactRepository;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
import org.eclipse.equinox.internal.provisional.p2.director.*;
import org.eclipse.equinox.internal.provisional.p2.engine.*;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.internal.provisional.p2.metadata.query.InstallableUnitQuery;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
import org.eclipse.equinox.internal.provisional.p2.query.Collector;
+import org.eclipse.equinox.internal.provisional.p2.query.Query;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
public class ProfileSynchronizer {
- private static final String FILE_LAST_MODIFIED = "file.lastModified"; //$NON-NLS-1$
- private static final String FILE_NAME = "file.name"; //$NON-NLS-1$
- private static final String REPOSITORY_ID = "repository.id"; //$NON-NLS-1$
- private IInstallableUnit[] iusToRemove;
- private IInstallableUnit[] iusToAdd;
- private IProfile profile;
- private List repositories;
+ public class ListCollector extends Collector {
+ public List getList() {
+ return super.getList();
+ }
+ }
+
+ private static final String SYNCH_REPOSITORY_ID = "synch.repository.id"; //$NON-NLS-1$
+ private static final String CACHE_EXTENSIONS = "org.eclipse.equinox.p2.cache.extensions"; //$NON-NLS-1$
+ private static final String PIPE = "|"; //$NON-NLS-1$
+ final IProfile profile;
+ final Map repositoryMap;
/*
* Constructor for the class.
*/
- public ProfileSynchronizer(IProfile profile, List repositories) {
- super();
+ public ProfileSynchronizer(IProfile profile, Collection repositories) {
this.profile = profile;
- this.repositories = repositories;
- initialize();
- }
-
- public void add(List additions) {
- this.repositories.addAll(repositories);
- initialize();
- // TODO progress monitoring
- synchronize(null);
- }
-
- /*
- * Initialize the synchronizer with default values.
- */
- private void initialize() {
- // snapshot is a table of all the IUs from this repository which are installed in the profile
- final Map snapshot = new HashMap();
- for (Iterator iter = repositories.iterator(); iter.hasNext();) {
- IMetadataRepository metadataRepository = (IMetadataRepository) iter.next();
- String repositoryId = metadataRepository.getLocation().toExternalForm();
- Iterator it = profile.query(InstallableUnitQuery.ANY, new Collector(), null).iterator();
- while (it.hasNext()) {
- IInstallableUnit iu = (IInstallableUnit) it.next();
- if (repositoryId.equals(iu.getProperty(REPOSITORY_ID))) {
- String fileName = iu.getProperty(FILE_NAME);
- if (fileName != null)
- snapshot.put(fileName, iu);
- }
- }
- }
-
- final List toAdd = new ArrayList();
- //create the collector that will visit all the IUs in the repositories being synchronized
- Collector syncCollector = new Collector() {
- public boolean accept(Object object) {
- IInstallableUnit iu = (IInstallableUnit) object;
- String iuFileName = iu.getProperty(FILE_NAME);
- // TODO is this right?
- if (iuFileName == null)
- return true;
-
- // if the repository contains an IU that the profile doesn't, then add it to the list to install
- IInstallableUnit profileIU = (IInstallableUnit) snapshot.get(iuFileName);
- if (profileIU == null) {
- toAdd.add(iu);
- return true;
- }
-
- Long iuLastModified = new Long(iu.getProperty(FILE_LAST_MODIFIED));
- Long profileIULastModified = new Long(profileIU.getProperty(FILE_LAST_MODIFIED));
- // TODO is this right?
- if (iuLastModified == null || profileIULastModified == null)
- return true;
-
- // if the timestamp hasn't changed, then there is nothing to do so remove
- // the IU from the snapshot so we don't accidentally remove it later
- if (iuLastModified.equals(profileIULastModified))
- snapshot.remove(iuFileName);
- else
- toAdd.add(iu);
- return true;
- }
- };
-
+ this.repositoryMap = new HashMap();
for (Iterator it = repositories.iterator(); it.hasNext();) {
- IMetadataRepository repo = (IMetadataRepository) it.next();
- // TODO report progress
- repo.query(InstallableUnitQuery.ANY, syncCollector, null);
- }
-
- // the IUs to remove is everything left that hasn't been removed from the snapshot
- if (!snapshot.isEmpty()) {
- iusToRemove = (IInstallableUnit[]) snapshot.values().toArray(new IInstallableUnit[snapshot.size()]);
- }
-
- // the list of IUs to add
- if (!toAdd.isEmpty()) {
- iusToAdd = (IInstallableUnit[]) toAdd.toArray(new IInstallableUnit[toAdd.size()]);
+ IMetadataRepository repository = (IMetadataRepository) it.next();
+ repositoryMap.put(repository.getLocation().toExternalForm(), repository);
}
}
/*
* Synchronize the profile with the list of metadata repositories.
*/
- public void synchronize(IProgressMonitor monitor) {
- IStatus status = Status.OK_STATUS;
- if (iusToRemove != null)
- status = removeIUs(iusToRemove, null); // TODO proper progress monitoring
- if (!status.isOK()) {
- // TODO
- throw new RuntimeException(new CoreException(status));
- }
+ public IStatus synchronize(IProgressMonitor monitor) {
- // disable repo cleanup for now until we see how we want to handle support for links folders and eclipse extensions
- //removeUnwatchedRepositories(context, profile, watchedFolder);
+ IStatus status = synchronizeCacheExtensions();
+ if (!status.isOK())
+ return status;
- if (iusToAdd != null)
- status = addIUs(iusToAdd, null); // TODO proper progress monitoring
- if (!status.isOK()) {
- // TODO
- throw new RuntimeException(new CoreException(status));
- }
- // if we did any work we have to apply the changes
- if (iusToAdd != null || iusToRemove != null)
- applyConfiguration();
- }
-
- /*
- * Install the given list of IUs.
- */
- private IStatus addIUs(IInstallableUnit[] toAdd, IProgressMonitor monitor) {
- BundleContext context = Activator.getContext();
+ ProfileChangeRequest request = createProfileChangeRequest();
+ if (request == null)
+ return Status.OK_STATUS;
SubMonitor sub = SubMonitor.convert(monitor, 100);
+ ProvisioningContext provisioningContext = new ProvisioningContext(new URL[0]);
- ServiceReference reference = context.getServiceReference(IPlanner.class.getName());
- IPlanner planner = (IPlanner) context.getService(reference);
+ ProvisioningPlan plan = createProvisioningPlan(request, provisioningContext, sub.newChild(50));
+ if (!plan.getStatus().isOK())
+ return plan.getStatus();
- try {
- ProfileChangeRequest request = new ProfileChangeRequest(profile);
- request.addInstallableUnits(toAdd);
- // mark the roots as such
- for (int i = 0; i < toAdd.length; i++) {
- if (Boolean.valueOf(toAdd[i].getProperty(IInstallableUnit.PROP_TYPE_GROUP)).booleanValue())
- request.setInstallableUnitProfileProperty(toAdd[i], IInstallableUnit.PROP_PROFILE_ROOT_IU, Boolean.toString(true));
+ if (plan.getOperands().length == 0) {
+ sub.done();
+ return Status.OK_STATUS;
+ }
+
+ status = executePlan(plan, provisioningContext, sub.newChild(50));
+ if (!status.isOK())
+ return status;
+
+ applyConfiguration();
+ return Status.OK_STATUS;
+ }
+
+ private IStatus synchronizeCacheExtensions() {
+ List currentExtensions = new ArrayList();
+ StringBuffer buffer = new StringBuffer();
+ for (Iterator it = repositoryMap.keySet().iterator(); it.hasNext();) {
+ String repositoryId = (String) it.next();
+ try {
+ IArtifactRepository repository = Activator.loadArtifactRepository(new URL(repositoryId));
+
+ if (repository instanceof IFileArtifactRepository) {
+ currentExtensions.add(repositoryId);
+ buffer.append(repositoryId);
+ if (it.hasNext())
+ buffer.append(PIPE);
+ }
+ } catch (ProvisionException e) {
+ // ignore
+ } catch (MalformedURLException e) {
+ // unexpected
+ e.printStackTrace();
}
-
- ProvisioningContext provisioningContext = new ProvisioningContext(new URL[0]);
- ProvisioningPlan plan = planner.getProvisioningPlan(request, provisioningContext, sub.newChild(50));
- if (!plan.getStatus().isOK())
- return plan.getStatus();
-
- return executePlan(plan, provisioningContext, sub.newChild(50));
-
- } finally {
- context.ungetService(reference);
}
+ String currentExtensionsProperty = (buffer.length() == 0) ? null : buffer.toString();
+
+ List previousExtensions = new ArrayList();
+ String previousExtensionsProperty = profile.getProperty(CACHE_EXTENSIONS);
+ if (previousExtensionsProperty != null) {
+ StringTokenizer tokenizer = new StringTokenizer(previousExtensionsProperty, PIPE);
+ while (tokenizer.hasMoreTokens()) {
+ previousExtensions.add(tokenizer.nextToken());
+ }
+ }
+
+ if (previousExtensions.size() == currentExtensions.size() && previousExtensions.containsAll(currentExtensions))
+ return Status.OK_STATUS;
+
+ Operand operand = new PropertyOperand(CACHE_EXTENSIONS, previousExtensionsProperty, currentExtensionsProperty);
+
+ return executeOperands(new ProvisioningContext(new URL[0]), new Operand[] {operand}, null);
}
- /*
- * Uninstall the given list of IUs.
- */
- private IStatus removeIUs(IInstallableUnit[] toRemove, IProgressMonitor monitor) {
+ private ProfileChangeRequest createProfileChangeRequest() {
+ boolean modified = false;
+ Collection profileIUs = getProfileIUs();
+ Collection toRemove = getStaleIUs();
+ profileIUs.removeAll(toRemove);
+
+ ProfileChangeRequest request = new ProfileChangeRequest(profile);
+ for (Iterator it = repositoryMap.entrySet().iterator(); it.hasNext();) {
+ Entry entry = (Entry) it.next();
+ String repositoryId = (String) entry.getKey();
+ IMetadataRepository repository = (IMetadataRepository) entry.getValue();
+ Iterator repositoryIterator = repository.query(InstallableUnitQuery.ANY, new Collector(), null).iterator();
+ while (repositoryIterator.hasNext()) {
+ IInstallableUnit iu = (IInstallableUnit) repositoryIterator.next();
+ if (profileIUs.contains(iu))
+ continue;
+
+ if (toRemove.contains(iu)) {
+ toRemove.remove(iu);
+ } else {
+ request.addInstallableUnits(new IInstallableUnit[] {iu});
+ if (Boolean.valueOf(iu.getProperty(IInstallableUnit.PROP_TYPE_GROUP)).booleanValue())
+ request.setInstallableUnitProfileProperty(iu, IInstallableUnit.PROP_PROFILE_ROOT_IU, Boolean.TRUE.toString());
+ }
+ request.setInstallableUnitProfileProperty(iu, SYNCH_REPOSITORY_ID, repositoryId);
+ profileIUs.add(iu);
+ modified = true;
+ }
+ }
+ if (!toRemove.isEmpty()) {
+ request.removeInstallableUnits((IInstallableUnit[]) toRemove.toArray(new IInstallableUnit[0]));
+ modified = true;
+ }
+
+ if (!modified)
+ return null;
+
+ return request;
+ }
+
+ private Collection getStaleIUs() {
+ Query removeQuery = new Query() {
+ public boolean isMatch(Object object) {
+ IInstallableUnit iu = (IInstallableUnit) object;
+ String repositoryId = profile.getInstallableUnitProperty(iu, SYNCH_REPOSITORY_ID);
+ if (repositoryId == null)
+ return false;
+
+ IMetadataRepository repo = (IMetadataRepository) repositoryMap.get(repositoryId);
+ Query iuQuery = new InstallableUnitQuery(iu.getId(), iu.getVersion());
+ return (repo == null || repo.query(iuQuery, new Collector(), null).isEmpty());
+ }
+ };
+
+ ListCollector listCollector = new ListCollector();
+ profile.query(removeQuery, listCollector, null);
+
+ List result = listCollector.getList();
+ return (result != null) ? result : Collections.EMPTY_LIST;
+ }
+
+ private List getProfileIUs() {
+ ListCollector listCollector = new ListCollector();
+ profile.query(InstallableUnitQuery.ANY, listCollector, null);
+
+ List result = listCollector.getList();
+ return (result != null) ? result : Collections.EMPTY_LIST;
+ }
+
+ private ProvisioningPlan createProvisioningPlan(ProfileChangeRequest request, ProvisioningContext provisioningContext, IProgressMonitor monitor) {
BundleContext context = Activator.getContext();
-
- SubMonitor sub = SubMonitor.convert(monitor, 100);
-
ServiceReference reference = context.getServiceReference(IPlanner.class.getName());
IPlanner planner = (IPlanner) context.getService(reference);
try {
- ProfileChangeRequest request = new ProfileChangeRequest(profile);
- request.removeInstallableUnits(toRemove);
-
- ProvisioningContext provisioningContext = new ProvisioningContext(new URL[0]);
- ProvisioningPlan plan = planner.getProvisioningPlan(request, provisioningContext, sub.newChild(50));
- if (!plan.getStatus().isOK())
- return plan.getStatus();
-
- return executePlan(plan, provisioningContext, sub.newChild(50));
-
+ return planner.getProvisioningPlan(request, provisioningContext, monitor);
} finally {
context.ungetService(reference);
}
}
private IStatus executePlan(ProvisioningPlan plan, ProvisioningContext provisioningContext, IProgressMonitor monitor) {
+ Operand[] operands = plan.getOperands();
+ return executeOperands(provisioningContext, operands, monitor);
+ }
+
+ private IStatus executeOperands(ProvisioningContext provisioningContext, Operand[] operands, IProgressMonitor monitor) {
BundleContext context = Activator.getContext();
ServiceReference reference = context.getServiceReference(IEngine.class.getName());
IEngine engine = (IEngine) context.getService(reference);
try {
PhaseSet phaseSet = new DefaultPhaseSet();
- IStatus engineResult = engine.perform(profile, phaseSet, plan.getOperands(), provisioningContext, monitor);
+ IStatus engineResult = engine.perform(profile, phaseSet, operands, provisioningContext, monitor);
return engineResult;
} finally {
context.ungetService(reference);
@@ -234,5 +243,4 @@
context.ungetService(reference);
}
}
-
}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/SiteInfo.java b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/SiteInfo.java
index e9c3e47..d891811 100644
--- a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/SiteInfo.java
+++ b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/SiteInfo.java
@@ -11,23 +11,21 @@
package org.eclipse.equinox.internal.p2.reconciler.dropins;
import org.eclipse.equinox.internal.p2.update.Site;
-import org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryWatcher;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
/*
* Internal class contains information about watchers and sites. Used for caching.
*/
public class SiteInfo {
- private DirectoryWatcher watcher;
- private SiteListener listener;
+ private IMetadataRepository repository;
private Site site;
private String url;
- public SiteInfo(Site site, DirectoryWatcher watcher, SiteListener listener) {
+ public SiteInfo(Site site, IMetadataRepository repository) {
super();
this.site = site;
this.url = site.getUrl();
- this.watcher = watcher;
- this.listener = listener;
+ this.repository = repository;
}
public Site getSite() {
@@ -38,12 +36,8 @@
return url;
}
- public DirectoryWatcher getWatcher() {
- return watcher;
- }
-
- public SiteListener getListener() {
- return listener;
+ public IMetadataRepository getRepository() {
+ return repository;
}
/* (non-Javadoc)
diff --git a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/SiteListener.java b/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/SiteListener.java
deleted file mode 100644
index f63e16b..0000000
--- a/bundles/org.eclipse.equinox.p2.reconciler/src/org/eclipse/equinox/internal/p2/reconciler/dropins/SiteListener.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2008 IBM Corporation 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:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.equinox.internal.p2.reconciler.dropins;
-
-import java.io.File;
-import org.eclipse.equinox.internal.p2.update.Site;
-import org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener;
-
-/**
- * @since 1.0
- */
-public class SiteListener extends RepositoryListener {
-
- private Site site;
-
- /*
- * Create a new site listener on the given site.
- */
- public SiteListener(Site site) {
- super(Activator.getContext(), Integer.toString(site.getUrl().hashCode()));
- this.site = site;
- }
-
- /*
- * Return true if the given list contains the symbolic name for the bundle
- * represented by the given file handle. Return false otherwise.
- */
- private boolean contains(String[] plugins, File file) {
- String filename = file.getAbsolutePath();
- for (int i = 0; i < plugins.length; i++)
- if (plugins[i].endsWith(filename))
- return true;
- return false;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryChangeListener#isInterested(java.io.File)
- */
- public boolean isInterested(File file) {
- String policy = site.getPolicy();
- String[] plugins = site.getList();
- if (Site.POLICY_MANAGED_ONLY.equals(policy)) {
- // TODO
- } else if (Site.POLICY_USER_EXCLUDE.equals(policy)) {
- // ensure the file doesn't refer to a plug-in in our list
- return plugins.length == 0 ? true : !contains(plugins, file);
- } else if (Site.POLICY_USER_INCLUDE.equals(policy)) {
- // we are only interested in plug-ins in the list
- return plugins.length == 0 ? false : contains(plugins, file);
- }
- return false;
- }
-}
diff --git a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/EclipseTouchpoint.java b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/EclipseTouchpoint.java
index 8464bce..4f57c42 100644
--- a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/EclipseTouchpoint.java
+++ b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/EclipseTouchpoint.java
@@ -891,7 +891,12 @@
featureVersion = artifactKey.getVersion().toString();
}
- return configuration.addFeatureEntry(featureId, featureVersion, artifactKey.getId(), artifactKey.getVersion().toString(), /*primary*/false, /*application*/null, /*root*/null);
+ IProfile profile = (IProfile) parameters.get(PARM_PROFILE);
+ File file = Util.getBundleFile(artifactKey, profile);
+ if (file == null || !file.exists()) {
+ // todo
+ }
+ return configuration.addFeatureEntry(file, featureId, featureVersion, artifactKey.getId(), artifactKey.getVersion().toString(), /*primary*/false, /*application*/null, /*root*/null);
}
protected IStatus uninstallFeature(Map parameters) {
diff --git a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/PlatformConfigurationWrapper.java b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/PlatformConfigurationWrapper.java
index 8f6b80c..0157c2e 100644
--- a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/PlatformConfigurationWrapper.java
+++ b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/PlatformConfigurationWrapper.java
@@ -11,6 +11,7 @@
package org.eclipse.equinox.internal.p2.touchpoint.eclipse;
import java.io.File;
+import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
@@ -55,38 +56,90 @@
throw new IllegalStateException("Error parsing platform configuration."); //$NON-NLS-1$;
}
- List sites = configuration.getSites();
- for (Iterator iter = sites.iterator(); iter.hasNext();) {
- Site nextSite = (Site) iter.next();
- String nextURL = nextSite.getUrl();
- if (new Path(nextURL).equals(new Path(poolURL.toExternalForm()))) {
- poolSite = nextSite;
- break;
- }
- }
-
+ poolSite = getSite(poolURL);
if (poolSite == null) {
- poolSite = new Site();
- poolSite.setUrl(poolURL.toExternalForm());
- poolSite.setPolicy(Site.POLICY_MANAGED_ONLY);
- poolSite.setEnabled(true);
+ poolSite = createSite(poolURL);
configuration.add(poolSite);
}
}
/*
+ * Create and return a site object based on the given location.
+ */
+ private Site createSite(URL location) {
+ Site result = new Site();
+ result.setUrl(location.toExternalForm());
+ result.setPolicy(Site.POLICY_MANAGED_ONLY);
+ result.setEnabled(true);
+ return result;
+ }
+
+ /*
+ * Look in the configuration and return the site object whose location matches
+ * the given URL. Return null if there is no match.
+ */
+ private Site getSite(URL url) {
+ List sites = configuration.getSites();
+ for (Iterator iter = sites.iterator(); iter.hasNext();) {
+ Site nextSite = (Site) iter.next();
+ String nextURL = nextSite.getUrl();
+ if (new Path(nextURL).equals(new Path(url.toExternalForm()))) {
+ return nextSite;
+ }
+ }
+ return null;
+ }
+
+ /*
+ * Look in the configuration and return the site which contains the feature
+ * with the given identifier and version. Return null if there is none.
+ */
+ private Site getSite(String id, String version) {
+ List sites = configuration.getSites();
+ for (Iterator iter = sites.iterator(); iter.hasNext();) {
+ Site site = (Site) iter.next();
+ Feature[] features = site.getFeatures();
+ for (int i = 0; i < features.length; i++) {
+ if (id.equals(features[i].getId()) && version.equals(features[i].getVersion()))
+ return site;
+ }
+ }
+ return null;
+ }
+
+ /*
* @see org.eclipse.update.configurator.IPlatformConfiguration#createFeatureEntry(java.lang.String, java.lang.String, java.lang.String, java.lang.String, boolean, java.lang.String, java.net.URL[])
*/
- public IStatus addFeatureEntry(String id, String version, String pluginIdentifier, String pluginVersion, boolean primary, String application, URL[] root) {
+ public IStatus addFeatureEntry(File file, String id, String version, String pluginIdentifier, String pluginVersion, boolean primary, String application, URL[] root) {
loadDelegate();
if (configuration == null)
return new Status(IStatus.WARNING, Activator.ID, "Platform configuration not available.", null); //$NON-NLS-1$
- Feature addedFeature = new Feature(poolSite);
+ URL fileURL = null;
+ try {
+ File featureDir = file.getParentFile();
+ if (featureDir == null || featureDir.getName().equals("features"))
+ return new Status(IStatus.ERROR, Activator.ID, "Parent directory should be \"features\": " + file.getAbsolutePath(), null);
+ File locationDir = featureDir.getParentFile();
+ if (locationDir == null)
+ return new Status(IStatus.ERROR, Activator.ID, "Unable to calculate extension location for: " + file.getAbsolutePath(), null);
+
+ fileURL = locationDir.toURL();
+ } catch (MalformedURLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return new Status(IStatus.ERROR, Activator.ID, "Unable to create URL from file: " + file.getAbsolutePath(), null);
+ }
+ Site site = getSite(fileURL);
+ if (site == null) {
+ site = createSite(fileURL);
+ configuration.add(site);
+ }
+ Feature addedFeature = new Feature(site);
addedFeature.setId(id);
addedFeature.setVersion(version);
addedFeature.setUrl(makeFeatureURL(id, version));
- poolSite.addFeature(addedFeature);
+ site.addFeature(addedFeature);
return Status.OK_STATUS;
}
@@ -98,7 +151,10 @@
if (configuration == null)
return new Status(IStatus.WARNING, Activator.ID, "Platform configuration not available.", null); //$NON-NLS-1$
- Feature removedFeature = poolSite.removeFeature(makeFeatureURL(id, version));
+ Site site = getSite(id, version);
+ if (site == null)
+ site = poolSite;
+ Feature removedFeature = site.removeFeature(makeFeatureURL(id, version));
return (removedFeature != null ? Status.OK_STATUS : new Status(IStatus.ERROR, Activator.ID, "A feature with the specified id was not found.", null)); //$NON-NLS-1$
}
diff --git a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/Util.java b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/Util.java
index 0c0e8aa..e807aa7 100644
--- a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/Util.java
+++ b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/Util.java
@@ -40,7 +40,8 @@
*/
private final static String CONFIG_FOLDER = "eclipse.configurationFolder"; //$NON-NLS-1$
private static final String REPOSITORY_TYPE = IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY;
- private static final Object PROFILE_EXTENSION = "profile.extension"; //$NON-NLS-1$
+ private static final String CACHE_EXTENSIONS = "org.eclipse.equinox.p2.cache.extensions"; //$NON-NLS-1$
+ private static final String PIPE = "|"; //$NON-NLS-1$
static AgentLocation getAgentLocation() {
return (AgentLocation) ServiceHelper.getService(Activator.getContext(), AgentLocation.class.getName());
@@ -90,20 +91,36 @@
bundleRepositories.add(Util.getBundlePoolRepository(profile));
IArtifactRepositoryManager manager = getArtifactRepositoryManager();
- URL[] knownRepositories = manager.getKnownRepositories(IArtifactRepositoryManager.REPOSITORIES_ALL);
- for (int i = 0; i < knownRepositories.length; i++) {
+ List extensions = getListProfileProperty(profile, CACHE_EXTENSIONS);
+ for (Iterator iterator = extensions.iterator(); iterator.hasNext();) {
try {
- IArtifactRepository repository = manager.loadRepository(knownRepositories[i], null);
- String profileExtension = (String) repository.getProperties().get(PROFILE_EXTENSION);
- if (profileExtension != null && profileExtension.equals(profile.getProfileId()))
+ String extension = (String) iterator.next();
+ URL extensionURL = new URL(extension);
+ IArtifactRepository repository = manager.loadRepository(extensionURL, null);
+ if (repository != null)
bundleRepositories.add(repository);
} catch (ProvisionException e) {
//skip repositories that could not be read
+ } catch (MalformedURLException e) {
+ // unexpected, URLs should be pre-checked
+ e.printStackTrace();
}
}
return new AggregatedBundleRepository(bundleRepositories);
}
+ private static List getListProfileProperty(IProfile profile, String key) {
+ List listProperty = new ArrayList();
+ String dropinRepositories = profile.getProperty(key);
+ if (dropinRepositories != null) {
+ StringTokenizer tokenizer = new StringTokenizer(dropinRepositories, PIPE);
+ while (tokenizer.hasMoreTokens()) {
+ listProperty.add(tokenizer.nextToken());
+ }
+ }
+ return listProperty;
+ }
+
static BundleInfo createBundleInfo(File bundleFile, String manifest) {
BundleInfo bundleInfo = new BundleInfo();
try {