diff options
19 files changed, 418 insertions, 36 deletions
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/AbstractRepositoryManager.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/AbstractRepositoryManager.java index 6bd47e168..623754f9b 100644 --- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/AbstractRepositoryManager.java +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/AbstractRepositoryManager.java @@ -22,7 +22,7 @@ public class AbstractRepositoryManager { protected void broadcastChangeEvent(URL location, int repositoryType, int kind) { IProvisioningEventBus bus = (IProvisioningEventBus) ServiceHelper.getService(Activator.getContext(), IProvisioningEventBus.class.getName()); if (bus != null) - bus.publishEvent(new RepositoryEvent(location, repositoryType, kind)); + bus.publishEvent(new RepositoryEvent(location, repositoryType, kind, true)); } } diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/ArtifactRepositoryManager.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/ArtifactRepositoryManager.java index 22f2a586e..2b6eaf0df 100644 --- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/ArtifactRepositoryManager.java +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/ArtifactRepositoryManager.java @@ -35,11 +35,13 @@ import org.osgi.service.prefs.Preferences; * * TODO the current assumption that the "location" is the dir/root limits us to * having just one repository in a given URL.. + * TODO Merge common parts with MetadataRepositoryManager */ public class ArtifactRepositoryManager extends AbstractRepositoryManager implements IArtifactRepositoryManager, ProvisioningListener { static class RepositoryInfo { String description; boolean isSystem = false; + boolean isEnabled = true; URL location; String name; SoftReference repository; @@ -105,9 +107,14 @@ public class ArtifactRepositoryManager extends AbstractRepositoryManager impleme } public void addRepository(URL location) { + addRepository(location, true); + } + + private void addRepository(URL location, boolean isEnabled) { Assert.isNotNull(location); RepositoryInfo info = new RepositoryInfo(); info.location = location; + info.isEnabled = isEnabled; boolean added = true; synchronized (repositoryLock) { if (repositories == null) @@ -387,6 +394,14 @@ public class ArtifactRepositoryManager extends AbstractRepositoryManager impleme if ((flags & REPOSITORIES_NON_SYSTEM) == REPOSITORIES_NON_SYSTEM) if (info.isSystem) return false; + if ((flags & REPOSITORIES_DISABLED) == REPOSITORIES_DISABLED) { + if (info.isEnabled) + return false; + } else { + //ignore disabled repositories for all other flag types + if (!info.isEnabled) + return false; + } if ((flags & REPOSITORIES_LOCAL) == REPOSITORIES_LOCAL) return "file".equals(info.location.getProtocol()); //$NON-NLS-1$ return true; @@ -399,7 +414,7 @@ public class ArtifactRepositoryManager extends AbstractRepositoryManager impleme if (o instanceof RepositoryEvent) { RepositoryEvent event = (RepositoryEvent) o; if (event.getKind() == RepositoryEvent.DISCOVERED && event.getRepositoryType() == IRepository.TYPE_ARTIFACT) - addRepository(event.getRepositoryLocation()); + addRepository(event.getRepositoryLocation(), event.isRepositoryEnabled()); } } @@ -578,4 +593,19 @@ public class ArtifactRepositoryManager extends AbstractRepositoryManager impleme log("Error while saving repositories in preferences", e); //$NON-NLS-1$ } } + + /*(non-Javadoc) + * @see org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepositoryManager#setEnabled(java.net.URL, boolean) + */ + public void setEnabled(URL location, boolean enablement) { + synchronized (repositoryLock) { + if (repositories == null) + restoreRepositories(); + RepositoryInfo info = (RepositoryInfo) repositories.get(getKey(location)); + if (info == null || info.isEnabled == enablement) + return; + info.isEnabled = enablement; + remember(info); + } + } } diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRepositoryManager.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRepositoryManager.java index 7c294f0bf..3e0033390 100644 --- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRepositoryManager.java +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRepositoryManager.java @@ -60,6 +60,12 @@ public interface IArtifactRepositoryManager { public static final int REPOSITORIES_LOCAL = 1 << 2; /** + * Constant used to indicate that disabled repositories are of interest. + * @see #getKnownRepositories(int) + */ + public static final int REPOSITORIES_DISABLED = 1 << 3; + + /** * Repository type for a simple repository based on a URL or local file system location. */ public static final String TYPE_SIMPLE_REPOSITORY = "org.eclipse.equinox.p2.artifact.repository.simpleRepository"; //$NON-NLS-1$ @@ -132,7 +138,7 @@ public interface IArtifactRepositoryManager { * * @param flags an integer bit-mask indicating which repositories should be * returned. <code>REPOSITORIES_ALL</code> can be used as the mask when - * all repositories should be returned. + * all enabled repositories should be returned. * * @return the locations of the repositories managed by this repository manager. * @@ -140,6 +146,7 @@ public interface IArtifactRepositoryManager { * @see #REPOSITORIES_SYSTEM * @see #REPOSITORIES_NON_SYSTEM * @see #REPOSITORIES_LOCAL + * @see #REPOSITORIES_DISABLED */ public URL[] getKnownRepositories(int flags); @@ -219,4 +226,24 @@ public interface IArtifactRepositoryManager { * <code>false</code> otherwise. */ public boolean removeRepository(URL location); + + /** + * Sets the enablement of a repository. Disabled repositories are known + * to the repository manager, but are never used in the context of provisioning + * operation. Disabled repositories are useful as a form of bookmark to indicate that a + * repository location is of interest, but not currently used. + * <p> + * Note that enablement is a property of the repository manager and not a property + * of the affected repository. The enablement of the repository is discarded when + * a repository is removed from the repository manager. + * <p> + * This method has no effect if the given repository location is not known to the + * repository manager. + * + * @param location The location of the repository to enable or disable + * @param enablement <code>true</code>to enable the repository, and + * <code>false</code> to disable the repository + * @see #REPOSITORIES_DISABLED + */ + public void setEnabled(URL location, boolean enablement); }
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/p2/persistence/XMLParser.java b/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/p2/persistence/XMLParser.java index bb0d8c0df..3be22a414 100644 --- a/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/p2/persistence/XMLParser.java +++ b/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/p2/persistence/XMLParser.java @@ -627,6 +627,16 @@ public abstract class XMLParser extends DefaultHandler implements XMLConstants { return result; } + // Check the format of a required integer attribute + public int checkInteger(String element, String attribute, String value) { + try { + return Integer.parseInt(value); + } catch (IllegalArgumentException iae) { + invalidAttributeValue(element, attribute, value); + } + return 0; + } + public void checkCancel() { if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException(); diff --git a/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/provisional/p2/core/repository/IRepository.java b/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/provisional/p2/core/repository/IRepository.java index c323e907c..cab96e4ea 100644 --- a/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/provisional/p2/core/repository/IRepository.java +++ b/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/provisional/p2/core/repository/IRepository.java @@ -58,16 +58,6 @@ public interface IRepository extends IAdaptable { public static final String PROP_TIMESTAMP = "p2.timestamp"; //$NON-NLS-1$ /** - * A repository type constant (value 0) representing a metadata repository. - */ - public static final int TYPE_METADATA = 0; - - /** - * A repository type constant (value 1) representing an artifact repository. - */ - public static final int TYPE_ARTIFACT = 1; - - /** * The key for a string property providing the user name to an authenticated * URL. This key is used in the secure preference store for repository data. * @see #PREFERENCE_NODE @@ -87,6 +77,27 @@ public interface IRepository extends IAdaptable { public static final String PREFERENCE_NODE = "org.eclipse.equinox.p2.repository"; //$NON-NLS-1$ /** + * A repository type constant (value 0) representing a metadata repository. + */ + public static final int TYPE_METADATA = 0; + + /** + * A repository type constant (value 1) representing an artifact repository. + */ + public static final int TYPE_ARTIFACT = 1; + + /** + * General purpose zero-valued bit mask constant. Useful whenever you need to + * supply a bit mask with no bits set. + */ + public static final int NONE = 0; + + /** + * An option flag constant (value 1) indicating an enabled repository. + */ + public static final int ENABLED = 1; + + /** * Returns the URL of the repository. * TODO: Should we use URL or URI? URL requires a protocol handler * to be installed in Java. Can the URL have any protocol? diff --git a/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/provisional/p2/core/repository/RepositoryEvent.java b/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/provisional/p2/core/repository/RepositoryEvent.java index 0a6964b75..31a51cb47 100644 --- a/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/provisional/p2/core/repository/RepositoryEvent.java +++ b/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/provisional/p2/core/repository/RepositoryEvent.java @@ -52,18 +52,21 @@ public class RepositoryEvent extends EventObject { private final int kind, type; + private boolean isEnabled; + /** * Creates a new repository event. * * @param location the location of the repository that changed. * @param repositoryType the type of repository that was changed * @param kind the kind of change that occurred. + * @param enabled whether the repository is enabled */ - public RepositoryEvent(URL location, int repositoryType, int kind) { + public RepositoryEvent(URL location, int repositoryType, int kind, boolean enabled) { super(location); this.kind = kind; this.type = repositoryType; - + isEnabled = enabled; } /** @@ -100,4 +103,14 @@ public class RepositoryEvent extends EventObject { return type; } + /** + * Returns whether the affected repository is enabled. + * + * @return <code>true</code> if the repository is enabled, + * and <code>false</code> otherwise. + */ + public boolean isRepositoryEnabled() { + return isEnabled; + } + } 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 da78ce5d4..11a91e951 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 @@ -95,20 +95,20 @@ public class RepositoryListener extends DirectoryChangeListener { return; URLEntry[] discoverySites = feature.getDiscoverySites(); for (int i = 0; i < discoverySites.length; i++) - publishSite(feature, bus, discoverySites[i].getURL()); + publishSite(feature, bus, discoverySites[i].getURL(), false); String updateSite = feature.getUpdateSiteURL(); if (updateSite != null) - publishSite(feature, bus, updateSite); + publishSite(feature, bus, updateSite, true); } /** * Broadcast a discovery event for the given repository location. */ - private void publishSite(Feature feature, IProvisioningEventBus bus, String locationString) { + private void publishSite(Feature feature, IProvisioningEventBus bus, String locationString, boolean isEnabled) { try { URL location = new URL(locationString); - bus.publishEvent(new RepositoryEvent(location, IRepository.TYPE_METADATA, RepositoryEvent.DISCOVERED)); - bus.publishEvent(new RepositoryEvent(location, IRepository.TYPE_ARTIFACT, RepositoryEvent.DISCOVERED)); + bus.publishEvent(new RepositoryEvent(location, IRepository.TYPE_METADATA, RepositoryEvent.DISCOVERED, isEnabled)); + bus.publishEvent(new RepositoryEvent(location, IRepository.TYPE_ARTIFACT, RepositoryEvent.DISCOVERED, isEnabled)); } catch (MalformedURLException e) { LogHelper.log(new Status(IStatus.WARNING, Activator.ID, "Feature references invalid site: " + feature.getId(), e)); //$NON-NLS-1$ } diff --git a/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepository.java b/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepository.java index b5940a0d9..fc381dc8d 100644 --- a/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepository.java +++ b/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepository.java @@ -21,11 +21,11 @@ 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.AbstractMetadataRepository; import org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.SimpleMetadataRepositoryFactory; import org.osgi.framework.BundleContext; -public class ExtensionLocationMetadataRepository extends AbstractRepository implements IMetadataRepository { +public class ExtensionLocationMetadataRepository extends AbstractMetadataRepository { private static final String POOLED = ".pooled"; //$NON-NLS-1$ private static final String ECLIPSE = "eclipse"; //$NON-NLS-1$ @@ -133,4 +133,8 @@ public class ExtensionLocationMetadataRepository extends AbstractRepository impl return metadataRepository.getProperties(); } + + public void initialize(RepositoryState state) { + //nothing to do + } } diff --git a/bundles/org.eclipse.equinox.p2.metadata.generator/src/org/eclipse/equinox/internal/provisional/p2/metadata/generator/Generator.java b/bundles/org.eclipse.equinox.p2.metadata.generator/src/org/eclipse/equinox/internal/provisional/p2/metadata/generator/Generator.java index c96526793..41b921776 100644 --- a/bundles/org.eclipse.equinox.p2.metadata.generator/src/org/eclipse/equinox/internal/provisional/p2/metadata/generator/Generator.java +++ b/bundles/org.eclipse.equinox.p2.metadata.generator/src/org/eclipse/equinox/internal/provisional/p2/metadata/generator/Generator.java @@ -9,6 +9,7 @@ package org.eclipse.equinox.internal.provisional.p2.metadata.generator; import java.io.*; +import java.net.MalformedURLException; import java.net.URL; import java.util.*; import java.util.Map.Entry; @@ -874,12 +875,24 @@ public class Generator { } + /** + * Generates metadata for the given features. + */ protected void generateFeatureIUs(Feature[] features, GeneratorResult result, IArtifactRepository destination) { Map categoriesToFeatureIUs = new HashMap(); Map featuresToCategories = getFeatureToCategoryMappings(); //Build Feature IUs, and add them to any corresponding categories for (int i = 0; i < features.length; i++) { Feature feature = features[i]; + //publish feature site references + String updateURL = feature.getUpdateSiteURL(); + if (updateURL != null) + generateSiteReference(updateURL, true); + URLEntry[] discoverySites = feature.getDiscoverySites(); + for (int j = 0; j < discoverySites.length; j++) + generateSiteReference(discoverySites[j].getURL(), false); + + //generate feature IU String location = feature.getLocation(); boolean isExploded = (location.endsWith(".jar") ? false : true); //$NON-NLS-1$ IInstallableUnit featureIU = MetadataGeneratorHelper.createFeatureJarIU(feature, isExploded); @@ -969,6 +982,23 @@ public class Generator { result.nonRootIUs.add(generateDefaultCategory(rootIU)); } + /** + * Generates and publishes a reference to an update site location + * @param location The update site location + * @param isEnabled Whether the site should be enabled by default + */ + private void generateSiteReference(String location, boolean isEnabled) { + IMetadataRepository metadataRepo = info.getMetadataRepository(); + try { + URL associateLocation = new URL(location); + int flags = isEnabled ? IRepository.ENABLED : IRepository.NONE; + metadataRepo.addReference(associateLocation, IRepository.TYPE_METADATA, flags); + metadataRepo.addReference(associateLocation, IRepository.TYPE_ARTIFACT, flags); + } catch (MalformedURLException e) { + LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Invalid site reference: " + location)); //$NON-NLS-1$ + } + } + protected BundleDescription[] getBundleDescriptions(File[] bundleLocations) { if (bundleLocations == null) return new BundleDescription[0]; @@ -1074,6 +1104,12 @@ public class Generator { info.getArtifactRepository().setProperty(IRepository.PROP_MIRRORS_URL, mirrors); } + //publish associate sites as repository references + URLEntry[] associatedSites = site.getAssociatedSites(); + if (associatedSites != null) + for (int i = 0; i < associatedSites.length; i++) + generateSiteReference(associatedSites[i].getURL(), true); + SiteFeature[] features = site.getFeatures(); for (int i = 0; i < features.length; i++) { //add a mapping for each category this feature belongs to diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/LocalMetadataRepository.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/LocalMetadataRepository.java index c2bea0f96..d9040bf50 100644 --- a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/LocalMetadataRepository.java +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/LocalMetadataRepository.java @@ -20,12 +20,15 @@ import org.eclipse.core.runtime.*; import org.eclipse.equinox.internal.p2.core.helpers.LogHelper; import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper; import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException; +import org.eclipse.equinox.internal.provisional.p2.core.eventbus.IProvisioningEventBus; import org.eclipse.equinox.internal.provisional.p2.core.repository.IRepository; +import org.eclipse.equinox.internal.provisional.p2.core.repository.RepositoryEvent; import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit; 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.equinox.internal.provisional.spi.p2.metadata.repository.AbstractMetadataRepository; +import org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.RepositoryReference; /** * A metadata repository that resides in the local file system. If the repository @@ -33,6 +36,7 @@ import org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.Abstr * and combine any metadata repository files that are found. */ public class LocalMetadataRepository extends AbstractMetadataRepository { + static final private String CONTENT_FILENAME = "content"; //$NON-NLS-1$ static final private String REPOSITORY_TYPE = LocalMetadataRepository.class.getName(); static final private Integer REPOSITORY_VERSION = new Integer(1); @@ -40,6 +44,7 @@ public class LocalMetadataRepository extends AbstractMetadataRepository { static final private String XML_EXTENSION = ".xml"; //$NON-NLS-1$ protected HashSet units = new LinkedHashSet(); + protected HashSet repositories = new HashSet(); private static File getActualLocation(URL location, String extension) { String spec = location.getFile(); @@ -83,6 +88,11 @@ public class LocalMetadataRepository extends AbstractMetadataRepository { save(); } + public void addReference(URL repositoryLocation, int repositoryType, int options) { + assertModifiable(); + repositories.add(new RepositoryReference(repositoryLocation, repositoryType, options)); + } + public void initialize(RepositoryState state) { this.name = state.Name; this.type = state.Type; @@ -92,6 +102,22 @@ public class LocalMetadataRepository extends AbstractMetadataRepository { this.location = state.Location; this.properties = state.Properties; this.units.addAll(Arrays.asList(state.Units)); + this.repositories.addAll(Arrays.asList(state.Repositories)); + publishRepositoryReferences(); + } + + /** + * Broadcast discovery events for all repositories referenced by this repository. + */ + private void publishRepositoryReferences() { + IProvisioningEventBus bus = (IProvisioningEventBus) ServiceHelper.getService(Activator.getContext(), IProvisioningEventBus.SERVICE_NAME); + if (bus == null) + return; + for (Iterator it = repositories.iterator(); it.hasNext();) { + RepositoryReference reference = (RepositoryReference) it.next(); + boolean isEnabled = (reference.Options & IRepository.ENABLED) != 0; + bus.publishEvent(new RepositoryEvent(reference.Location, reference.Type, RepositoryEvent.DISCOVERED, isEnabled)); + } } // use this method to setup any transient fields etc after the object has been restored from a stream diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryIO.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryIO.java index 20cf187d9..2b2f3003c 100644 --- a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryIO.java +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryIO.java @@ -13,6 +13,8 @@ package org.eclipse.equinox.internal.p2.metadata.repository; import java.io.*; import java.net.URL; +import java.util.Iterator; +import java.util.Set; import javax.xml.parsers.ParserConfigurationException; import org.eclipse.core.runtime.*; import org.eclipse.equinox.internal.p2.core.helpers.LogHelper; @@ -26,6 +28,7 @@ import org.eclipse.equinox.internal.provisional.p2.metadata.query.InstallableUni 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.spi.p2.metadata.repository.AbstractMetadataRepository; +import org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.RepositoryReference; import org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.AbstractMetadataRepository.RepositoryState; import org.eclipse.osgi.service.resolver.VersionRange; import org.eclipse.osgi.util.NLS; @@ -130,11 +133,38 @@ public class MetadataRepositoryIO { writeProperties(repository.getProperties()); Collector units = repository.query(InstallableUnitQuery.ANY, new Collector(), null); + if (repository instanceof LocalMetadataRepository) { + Set references = ((LocalMetadataRepository) repository).repositories; + writeRepositoryReferences(references.iterator(), references.size()); + } writeInstallableUnits(units.iterator(), units.size()); end(REPOSITORY_ELEMENT); flush(); } + + /** + * Writes a list of {@link RepositoryReference}. + * @param references An Iterator of {@link RepositoryReference}. + * @param size The number of references to write + */ + protected void writeRepositoryReferences(Iterator references, int size) { + if (size == 0) + return; + start(REPOSITORY_REFERENCES_ELEMENT); + attribute(COLLECTION_SIZE_ATTRIBUTE, size); + while (references.hasNext()) + writeRepositoryReference((RepositoryReference) references.next()); + end(REPOSITORY_REFERENCES_ELEMENT); + } + + private void writeRepositoryReference(RepositoryReference reference) { + start(REPOSITORY_REFERENCE_ELEMENT); + attribute(URL_ATTRIBUTE, reference.Location.toExternalForm()); + attribute(TYPE_ATTRIBUTE, Integer.toString(reference.Type)); + attribute(OPTIONS_ATTRIBUTE, Integer.toString(reference.Options)); + end(REPOSITORY_REFERENCE_ELEMENT); + } } /* @@ -210,6 +240,7 @@ public class MetadataRepositoryIO { private InstallableUnitsHandler unitsHandler = null; private PropertiesHandler propertiesHandler = null; + private RepositoryReferencesHandler repositoryReferencesHandler = null; private AbstractMetadataRepository repository = null; @@ -259,6 +290,7 @@ public class MetadataRepositoryIO { : propertiesHandler.getProperties()); state.Units = (unitsHandler == null ? new IInstallableUnit[0] // : unitsHandler.getUnits()); + state.Repositories = repositoryReferencesHandler == null ? new RepositoryReference[0] : repositoryReferencesHandler.getReferences(); try { //can't create repository if missing type - this is already logged when parsing attributes if (state.Type == null) diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryManager.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryManager.java index cc75862df..eae5da92f 100644 --- a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryManager.java +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryManager.java @@ -38,6 +38,7 @@ public class MetadataRepositoryManager implements IMetadataRepositoryManager, Pr static class RepositoryInfo { String description; boolean isSystem = false; + boolean isEnabled = true; URL location; String name; SoftReference repository; @@ -105,9 +106,14 @@ public class MetadataRepositoryManager implements IMetadataRepositoryManager, Pr } public void addRepository(URL location) { + addRepository(location, true); + } + + private void addRepository(URL location, boolean isEnabled) { Assert.isNotNull(location); RepositoryInfo info = new RepositoryInfo(); info.location = location; + info.isEnabled = isEnabled; boolean added = true; synchronized (repositoryLock) { if (repositories == null) @@ -126,7 +132,7 @@ public class MetadataRepositoryManager implements IMetadataRepositoryManager, Pr protected void broadcastChangeEvent(URL location, int repositoryType, int kind) { IProvisioningEventBus bus = (IProvisioningEventBus) ServiceHelper.getService(Activator.getContext(), IProvisioningEventBus.class.getName()); if (bus != null) - bus.publishEvent(new RepositoryEvent(location, repositoryType, kind)); + bus.publishEvent(new RepositoryEvent(location, repositoryType, kind, true)); } /** @@ -412,6 +418,14 @@ public class MetadataRepositoryManager implements IMetadataRepositoryManager, Pr if ((flags & REPOSITORIES_NON_SYSTEM) == REPOSITORIES_NON_SYSTEM) if (info.isSystem) return false; + if ((flags & REPOSITORIES_DISABLED) == REPOSITORIES_DISABLED) { + if (info.isEnabled) + return false; + } else { + //ignore disabled repositories for all other flag types + if (!info.isEnabled) + return false; + } if ((flags & REPOSITORIES_LOCAL) == REPOSITORIES_LOCAL) return "file".equals(info.location.getProtocol()); //$NON-NLS-1$ return true; @@ -424,7 +438,7 @@ public class MetadataRepositoryManager implements IMetadataRepositoryManager, Pr if (o instanceof RepositoryEvent) { RepositoryEvent event = (RepositoryEvent) o; if (event.getKind() == RepositoryEvent.DISCOVERED && event.getRepositoryType() == IRepository.TYPE_METADATA) - addRepository(event.getRepositoryLocation()); + addRepository(event.getRepositoryLocation(), event.isRepositoryEnabled()); } } @@ -627,6 +641,21 @@ public class MetadataRepositoryManager implements IMetadataRepositoryManager, Pr } } + /*(non-Javadoc) + * @see org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager#setEnabled(java.net.URL, boolean) + */ + public void setEnabled(URL location, boolean enablement) { + synchronized (repositoryLock) { + if (repositories == null) + restoreRepositories(); + RepositoryInfo info = (RepositoryInfo) repositories.get(getKey(location)); + if (info == null || info.isEnabled == enablement) + return; + info.isEnabled = enablement; + remember(info); + } + } + public IStatus validateRepositoryLocation(URL location, IProgressMonitor monitor) { Assert.isNotNull(location); IMetadataRepository result = getRepository(location); diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/MetadataParser.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/MetadataParser.java index 72f27e3ad..bc2023ffd 100644 --- a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/MetadataParser.java +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/MetadataParser.java @@ -11,6 +11,8 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.metadata.repository.io; +import java.net.MalformedURLException; +import java.net.URL; import java.util.*; import org.eclipse.equinox.internal.p2.core.helpers.OrderedProperties; import org.eclipse.equinox.internal.p2.metadata.ArtifactKey; @@ -18,6 +20,7 @@ import org.eclipse.equinox.internal.p2.persistence.XMLParser; import org.eclipse.equinox.internal.provisional.p2.metadata.*; import org.eclipse.equinox.internal.provisional.p2.metadata.MetadataFactory.InstallableUnitDescription; import org.eclipse.equinox.internal.provisional.p2.metadata.MetadataFactory.InstallableUnitFragmentDescription; +import org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.RepositoryReference; import org.eclipse.osgi.service.resolver.VersionRange; import org.osgi.framework.BundleContext; import org.osgi.framework.Version; @@ -30,6 +33,49 @@ public abstract class MetadataParser extends XMLParser implements XMLConstants { super(context, bundleId); } + protected class RepositoryReferencesHandler extends AbstractHandler { + private HashSet references; + + public RepositoryReferencesHandler(AbstractHandler parentHandler, Attributes attributes) { + super(parentHandler, REPOSITORY_REFERENCES_ELEMENT); + String size = parseOptionalAttribute(attributes, COLLECTION_SIZE_ATTRIBUTE); + references = (size != null ? new HashSet(Integer.parseInt(size)) : new HashSet(4)); + } + + public void startElement(String name, Attributes attributes) { + if (name.equals(REPOSITORY_REFERENCE_ELEMENT)) { + new RepositoryReferenceHandler(this, attributes, references); + } else { + invalidElement(name, attributes); + } + } + + public RepositoryReference[] getReferences() { + return (RepositoryReference[]) references.toArray(new RepositoryReference[references.size()]); + } + } + + protected class RepositoryReferenceHandler extends AbstractHandler { + + private final String[] required = new String[] {URL_ATTRIBUTE, TYPE_ATTRIBUTE, OPTIONS_ATTRIBUTE}; + + public RepositoryReferenceHandler(AbstractHandler parentHandler, Attributes attributes, Set references) { + super(parentHandler, REPOSITORY_REFERENCE_ELEMENT); + String[] values = parseRequiredAttributes(attributes, required); + try { + int type = checkInteger(elementHandled, TYPE_ATTRIBUTE, values[1]); + int options = checkInteger(elementHandled, OPTIONS_ATTRIBUTE, values[2]); + references.add(new RepositoryReference(new URL(values[0]), type, options)); + } catch (MalformedURLException e) { + invalidAttributeValue(elementHandled, URL_ATTRIBUTE, values[0]); + } + } + + public void startElement(String name, Attributes attributes) { + invalidElement(name, attributes); + } + } + protected class InstallableUnitsHandler extends AbstractHandler { private ArrayList units; diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/XMLConstants.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/XMLConstants.java index 5e7957a7f..df7a61fdb 100644 --- a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/XMLConstants.java +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/XMLConstants.java @@ -28,6 +28,11 @@ public interface XMLConstants extends org.eclipse.equinox.internal.p2.persistenc public static final String INSTALLABLE_UNITS_ELEMENT = "units"; //$NON-NLS-1$ public static final String INSTALLABLE_UNIT_ELEMENT = "unit"; //$NON-NLS-1$ + //Constants for repository references + public static final String REPOSITORY_REFERENCES_ELEMENT = "references"; //$NON-NLS-1$ + public static final String REPOSITORY_REFERENCE_ELEMENT = "repository"; //$NON-NLS-1$ + public static final String OPTIONS_ATTRIBUTE = "options"; //$NON-NLS-1$ + // Constants for sub-elements of an installable unit element public static final String ARTIFACT_KEYS_ELEMENT = "artifacts"; //$NON-NLS-1$ public static final String ARTIFACT_KEY_ELEMENT = "artifact"; //$NON-NLS-1$ diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/provisional/p2/metadata/repository/IMetadataRepository.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/provisional/p2/metadata/repository/IMetadataRepository.java index 48e607e1b..867fc84ed 100644 --- a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/provisional/p2/metadata/repository/IMetadataRepository.java +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/provisional/p2/metadata/repository/IMetadataRepository.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.equinox.internal.provisional.p2.metadata.repository; +import java.net.URL; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.equinox.internal.provisional.p2.core.repository.IRepository; import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit; @@ -34,6 +35,30 @@ public interface IMetadataRepository extends IRepository, IQueryable { public void addInstallableUnits(IInstallableUnit[] installableUnits); /** + * Adds a reference to another repository to this repository. When a repository + * is loaded by {@link IMetadataRepositoryManager}, its references + * are automatically added to the repository manager's set of known repositories. + * <p> + * Note that this method does not add the <b>contents</b> of the given + * repository to this repository, but merely adds the location of another + * repository to the metadata of this repository. + * <p> + * The {@link IRepository#ENABLED} option flag controls whether the + * referenced repository should be marked as enabled when added to the repository + * manager. If this flag is set, the repository will be marked as enabled when + * added to the repository manager. If this flag is missing, the repository will + * be marked as disabled. + * + * @param location the location of the repository to add + * @param type the repository type (currently either {@link IRepository#TYPE_METADATA} + * or {@link IRepository#TYPE_ARTIFACT}). + * @param options bit-wise or of option constants (currently either + * {@link IRepository#ENABLED} or {@link IRepository#NONE}). + * @see IMetadataRepositoryManager#setEnabled(URL, boolean) + */ + public void addReference(URL location, int type, int options); + + /** * Removes all installable units that match the given query from this repository. * * @param query the installable units to remove diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/provisional/p2/metadata/repository/IMetadataRepositoryManager.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/provisional/p2/metadata/repository/IMetadataRepositoryManager.java index 03d3c9401..0da293786 100644 --- a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/provisional/p2/metadata/repository/IMetadataRepositoryManager.java +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/provisional/p2/metadata/repository/IMetadataRepositoryManager.java @@ -32,7 +32,7 @@ import org.eclipse.equinox.internal.provisional.p2.query.IQueryable; public interface IMetadataRepositoryManager extends IQueryable { /** - * Constant used to indicate that all repositories are of interest. + * Constant used to indicate that all enabled repositories are of interest. */ public static final int REPOSITORIES_ALL = 0; @@ -57,6 +57,12 @@ public interface IMetadataRepositoryManager extends IQueryable { public static final int REPOSITORIES_LOCAL = 1 << 2; /** + * Constant used to indicate that disabled repositories are of interest. + * @see #getKnownRepositories(int) + */ + public static final int REPOSITORIES_DISABLED = 1 << 3; + + /** * Repository type for a simple repository based on a URL or local file system location. */ public static final String TYPE_SIMPLE_REPOSITORY = "org.eclipse.equinox.p2.metadata.repository.simpleRepository"; //$NON-NLS-1$ @@ -102,7 +108,7 @@ public interface IMetadataRepositoryManager extends IQueryable { * * @param flags an integer bit-mask indicating which repositories should be * returned. <code>REPOSITORIES_ALL</code> can be used as the mask when - * all repositories should be returned. Where multiple masks are combined, only + * all enabled repositories should be returned. Where multiple masks are combined, only * the repositories that satisfy all the given criteria are returned. For example, * a flag value of (REPOSITORIES_SYSTEM|REPOSITORIES_LOCAL) will only * return repositories that are both system and local repositories. @@ -113,6 +119,7 @@ public interface IMetadataRepositoryManager extends IQueryable { * @see #REPOSITORIES_SYSTEM * @see #REPOSITORIES_LOCAL * @see #REPOSITORIES_NON_SYSTEM + * @see #REPOSITORIES_DISABLED */ public URL[] getKnownRepositories(int flags); @@ -195,6 +202,26 @@ public interface IMetadataRepositoryManager extends IQueryable { public boolean removeRepository(URL location); /** + * Sets the enablement of a repository. Disabled repositories are known + * to the repository manager, but are never used in the context of provisioning + * operation. Disabled repositories are useful as a form of bookmark to indicate that a + * repository location is of interest, but not currently used. + * <p> + * Note that enablement is a property of the repository manager and not a property + * of the affected repository. The enablement of the repository is discarded when + * a repository is removed from the repository manager. + * <p> + * This method has no effect if the given repository location is not known to the + * repository manager. + * + * @param location The location of the repository to enable or disable + * @param enablement <code>true</code>to enable the repository, and + * <code>false</code> to disable the repository + * @see #REPOSITORIES_DISABLED + */ + public void setEnabled(URL location, boolean enablement); + + /** * Validates a given URL and returns a status indicating whether a valid repository is likely * to be found at the given URL. Callers must assume that the validity of a * repository location cannot be completely determined until an attempt to load diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/provisional/spi/p2/metadata/repository/AbstractMetadataRepository.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/provisional/spi/p2/metadata/repository/AbstractMetadataRepository.java index 3b18bcd33..4ad53ad7e 100644 --- a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/provisional/spi/p2/metadata/repository/AbstractMetadataRepository.java +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/provisional/spi/p2/metadata/repository/AbstractMetadataRepository.java @@ -36,6 +36,7 @@ public abstract class AbstractMetadataRepository extends AbstractRepository impl public URL Location; public Map Properties; public IInstallableUnit[] Units; + public RepositoryReference[] Repositories; } public AbstractMetadataRepository() { @@ -49,18 +50,19 @@ public abstract class AbstractMetadataRepository extends AbstractRepository impl } public void addInstallableUnits(IInstallableUnit[] installableUnit) { - if (!isModifiable()) - throw new UnsupportedOperationException("Repository not modifiable"); + assertModifiable(); + } + + public void addReference(URL repositoryLocation, int repositoryType, int options) { + assertModifiable(); } public void removeAll() { - if (!isModifiable()) - throw new UnsupportedOperationException("Repository not modifiable"); + assertModifiable(); } public boolean removeInstallableUnits(Query query, IProgressMonitor monitor) { - if (!isModifiable()) - throw new UnsupportedOperationException("Repository not modifiable"); + assertModifiable(); return false; } diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/provisional/spi/p2/metadata/repository/RepositoryReference.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/provisional/spi/p2/metadata/repository/RepositoryReference.java new file mode 100644 index 000000000..c9c985e52 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/provisional/spi/p2/metadata/repository/RepositoryReference.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * 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.provisional.spi.p2.metadata.repository; + +import java.net.URL; + +/** + * Serialization helper class for repository references. + */ +public class RepositoryReference { + public URL Location; + public int Type; + public int Options; + + public RepositoryReference(URL location, int type, int options) { + this.Location = location; + this.Type = type; + this.Options = options; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RepositoryReference other = (RepositoryReference) obj; + if (Location == null) { + if (other.Location != null) + return false; + } else if (!Location.equals(other.Location)) + return false; + if (Type != other.Type) + return false; + return true; + } + + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((Location == null) ? 0 : Location.hashCode()); + result = prime * result + Type; + return result; + } + +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/metadata/UpdateSiteMetadataRepository.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/metadata/UpdateSiteMetadataRepository.java index 4dc0d22a9..946a49f28 100644 --- a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/metadata/UpdateSiteMetadataRepository.java +++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/metadata/UpdateSiteMetadataRepository.java @@ -30,13 +30,13 @@ import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*; 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.AbstractMetadataRepository; import org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.SimpleMetadataRepositoryFactory; import org.eclipse.osgi.service.resolver.*; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; -public class UpdateSiteMetadataRepository extends AbstractRepository implements IMetadataRepository { +public class UpdateSiteMetadataRepository extends AbstractMetadataRepository { private final IMetadataRepository metadataRepository; private static final String FEATURE_VERSION_SEPARATOR = "_"; //$NON-NLS-1$ @@ -88,8 +88,8 @@ public class UpdateSiteMetadataRepository extends AbstractRepository implements for (int i = 0; i < sites.length; i++) { try { URL siteLocation = new URL(sites[i].getURL()); - bus.publishEvent(new RepositoryEvent(siteLocation, IRepository.TYPE_METADATA, RepositoryEvent.DISCOVERED)); - bus.publishEvent(new RepositoryEvent(siteLocation, IRepository.TYPE_ARTIFACT, RepositoryEvent.DISCOVERED)); + bus.publishEvent(new RepositoryEvent(siteLocation, IRepository.TYPE_METADATA, RepositoryEvent.DISCOVERED, true)); + bus.publishEvent(new RepositoryEvent(siteLocation, IRepository.TYPE_ARTIFACT, RepositoryEvent.DISCOVERED, true)); } catch (MalformedURLException e) { LogHelper.log(new Status(IStatus.WARNING, Activator.ID, "Site has invalid associate site: " + baseSite.getLocation(), e)); //$NON-NLS-1$ } @@ -230,4 +230,8 @@ public class UpdateSiteMetadataRepository extends AbstractRepository implements return metadataRepository.removeInstallableUnits(query, monitor); } + public void initialize(RepositoryState state) { + //nothing to do + } + } |