/******************************************************************************* * Copyright (c) 2010 The Eclipse Foundation 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: * The Eclipse Foundation - initial API and implementation *******************************************************************************/ package org.eclipse.epp.internal.mpc.ui.operations; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.epp.internal.mpc.core.util.URLUtil; import org.eclipse.equinox.internal.p2.discovery.model.CatalogItem; import org.eclipse.equinox.p2.core.ProvisionException; import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.equinox.p2.operations.ProvisioningSession; import org.eclipse.equinox.p2.operations.RepositoryTracker; import org.eclipse.equinox.p2.query.IQuery; import org.eclipse.equinox.p2.query.IQueryResult; import org.eclipse.equinox.p2.query.QueryUtil; import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager; import org.eclipse.equinox.p2.ui.ProvisioningUI; import org.eclipse.jface.operation.IRunnableWithProgress; public abstract class AbstractProvisioningOperation implements IRunnableWithProgress { protected static final String P2_FEATURE_GROUP_SUFFIX = ".feature.group"; //$NON-NLS-1$ protected final List<CatalogItem> items; protected final ProvisioningUI provisioningUI; protected Set<URI> repositoryLocations; protected Set<URI> addedRepositoryLocations; protected AbstractProvisioningOperation(Collection<CatalogItem> installableConnectors) { if (installableConnectors == null || installableConnectors.isEmpty()) { throw new IllegalArgumentException(); } this.items = new ArrayList<CatalogItem>(installableConnectors); this.provisioningUI = ProvisioningUI.getDefaultUI(); } protected List<IMetadataRepository> addRepositories(SubMonitor monitor) throws URISyntaxException, ProvisionException { // tell p2 that it's okay to use these repositories ProvisioningSession session = ProvisioningUI.getDefaultUI().getSession(); RepositoryTracker repositoryTracker = ProvisioningUI.getDefaultUI().getRepositoryTracker(); repositoryLocations = new HashSet<URI>(); if (addedRepositoryLocations == null) { addedRepositoryLocations = new HashSet<URI>(); } Set<URI> knownRepositories = new HashSet<URI>(Arrays.asList(repositoryTracker.getKnownRepositories(session))); monitor.setWorkRemaining(items.size() * 5); for (CatalogItem descriptor : items) { String siteUrl = descriptor.getSiteUrl(); if (siteUrl != null) { URI uri = URLUtil.toURI(siteUrl); if (repositoryLocations.add(uri) && !knownRepositories.contains(uri)) { checkCancelled(monitor); repositoryTracker.addRepository(uri, null, session); addedRepositoryLocations.add(uri); } } monitor.worked(1); } // fetch meta-data for these repositories ArrayList<IMetadataRepository> repositories = new ArrayList<IMetadataRepository>(); monitor.setWorkRemaining(repositories.size()); IMetadataRepositoryManager manager = (IMetadataRepositoryManager) session.getProvisioningAgent().getService( IMetadataRepositoryManager.SERVICE_NAME); for (URI uri : repositoryLocations) { checkCancelled(monitor); IMetadataRepository repository = manager.loadRepository(uri, monitor.newChild(1)); repositories.add(repository); } return repositories; } /** * Perform a query to get the installable units. This causes p2 to determine what features are available in each * repository. We select installable units by matching both the feature id and the repository; it is possible though * unlikely that the same feature id is available from more than one of the selected repositories, and we must * ensure that the user gets the one that they asked for. */ protected List<IInstallableUnit> queryInstallableUnits(SubMonitor monitor, List<IMetadataRepository> repositories) throws URISyntaxException { final List<IInstallableUnit> installableUnits = new ArrayList<IInstallableUnit>(); monitor.setWorkRemaining(repositories.size()); for (final IMetadataRepository repository : repositories) { checkCancelled(monitor); final Set<String> installableUnitIdsThisRepository = getDescriptorIds(repository); IQuery<IInstallableUnit> query = QueryUtil.createLatestQuery(QueryUtil.createIUGroupQuery()); IQueryResult<IInstallableUnit> result = repository.query(query, monitor.newChild(1)); for (IInstallableUnit iu : result) { String id = iu.getId(); if (installableUnitIdsThisRepository.contains(id)) { installableUnits.add(iu); } } } return installableUnits; } private Set<String> getDescriptorIds(final IMetadataRepository repository) throws URISyntaxException { final Set<String> installableUnitIdsThisRepository = new HashSet<String>(); // determine all installable units for this repository for (CatalogItem descriptor : items) { if (descriptor.getSiteUrl() != null && repository.getLocation().equals(URLUtil.toURI(descriptor.getSiteUrl()))) { installableUnitIdsThisRepository.addAll(getFeatureIds(descriptor)); } } return installableUnitIdsThisRepository; } protected Set<String> getFeatureIds(CatalogItem descriptor) { Set<String> featureIds = new HashSet<String>(); for (String id : descriptor.getInstallableUnits()) { if (!id.endsWith(P2_FEATURE_GROUP_SUFFIX)) { id += P2_FEATURE_GROUP_SUFFIX; } featureIds.add(id); } return featureIds; } protected void checkCancelled(IProgressMonitor monitor) { if (monitor.isCanceled()) { throw new OperationCanceledException(); } } public Set<URI> getAddedRepositoryLocations() { return addedRepositoryLocations; } protected void removeAddedRepositoryLocations() { if (addedRepositoryLocations != null) { removeRepositoryLocations(addedRepositoryLocations); addedRepositoryLocations = null; } } /** * remove the given repository locations from the repository tracker. * * @param repositoryLocations */ public static void removeRepositoryLocations(Set<URI> repositoryLocations) { if (repositoryLocations == null || repositoryLocations.isEmpty()) { return; } ProvisioningSession session = ProvisioningUI.getDefaultUI().getSession(); RepositoryTracker repositoryTracker = ProvisioningUI.getDefaultUI().getRepositoryTracker(); repositoryTracker.removeRepositories(repositoryLocations.toArray(new URI[repositoryLocations.size()]), session); } }