core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/FeatureInstallOperation.java
/*
* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
package com.nokia.carbide.internal.discovery.ui.wizard;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.operations.InstallOperation;
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.IQueryable;
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;
import org.eclipse.swt.widgets.Display;
import com.nokia.carbide.discovery.ui.Messages;
class FeatureInstallOperation implements IRunnableWithProgress {
private Collection<URI> uris;
private Collection<FeatureInfo> featureInfos;
private boolean wantVersions;
private ProvisioningUI provisioningUI;
private Collection<IMetadataRepository> repositories;
private Collection<IInstallableUnit> ius;
private Collection<URI> urisUsed;
public FeatureInstallOperation(Collection<URI> uris, Collection<FeatureInfo> featureInfos, boolean wantVersions) {
this.uris = uris;
this.featureInfos = featureInfos;
this.wantVersions = wantVersions;
provisioningUI = ProvisioningUI.getDefaultUI();
}
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
doInstall(monitor);
} catch (OperationCanceledException e) {
throw new InterruptedException();
} catch (CoreException e) {
throw new InvocationTargetException(e);
}
}
public void doInstall(IProgressMonitor monitor) throws OperationCanceledException, CoreException {
SubMonitor subMonitor = SubMonitor.convert(monitor, Messages.FeatureInstallOperation_ConfiguringTaskName, 100);
getRepositories(subMonitor.newChild(30));
findInstallableUnits(subMonitor.newChild(40));
final InstallOperation operation = resolve(subMonitor.newChild(30));
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
IQueryable<IInstallableUnit> additions = operation.getProvisioningPlan().getAdditions();
IQueryResult<IInstallableUnit> result = additions.query(QueryUtil.createIUGroupQuery(), new NullProgressMonitor());
provisioningUI.openInstallWizard(result.toSet(), operation, null);
}
});
}
private void getRepositories(SubMonitor monitor) throws ProvisionException, OperationCanceledException {
monitor.setWorkRemaining(uris.size());
repositories = new ArrayList<IMetadataRepository>();
ProvisioningSession session = provisioningUI.getSession();
RepositoryTracker repositoryTracker = provisioningUI.getRepositoryTracker();
IMetadataRepositoryManager manager =
(IMetadataRepositoryManager) session.getProvisioningAgent().getService(IMetadataRepositoryManager.SERVICE_NAME);
for (URI uri : uris) {
checkIfCanceled(monitor);
repositoryTracker.addRepository(uri, null, session);
repositories.add(manager.loadRepository(uri, monitor.newChild(1)));
}
}
private void findInstallableUnits(SubMonitor monitor) throws ProvisionException {
monitor.setWorkRemaining(repositories.size() * featureInfos.size());
ius = new ArrayList<IInstallableUnit>();
urisUsed = new HashSet<URI>();
Set<FeatureInfo> remainingInfos = new HashSet<FeatureInfo>(featureInfos);
for (IMetadataRepository repository : repositories) {
checkIfCanceled(monitor);
IQueryResult<IInstallableUnit> iusInRepository = repository.query(QueryUtil.createIUGroupQuery(), monitor.newChild(1));
for (FeatureInfo featureInfo : new HashSet<FeatureInfo>(remainingInfos)) {
String id = featureInfo.getId();
IQuery<IInstallableUnit> iuQuery = wantVersions ?
QueryUtil.createIUQuery(id, featureInfo.getVersion()) :
QueryUtil.createLatestQuery(QueryUtil.createIUQuery(id));
IQueryResult<IInstallableUnit> result = iusInRepository.query(iuQuery, monitor.newChild(1));
if (!result.isEmpty()) {
ius.add(result.iterator().next());
urisUsed.add(repository.getLocation());
remainingInfos.remove(featureInfo);
if (remainingInfos.isEmpty())
break;
}
}
}
if (!remainingInfos.isEmpty()) {
StringBuilder sb = new StringBuilder();
sb.append(Messages.FeatureInstallOperation_MissingFeaturesError);
for (FeatureInfo featureInfo : remainingInfos) {
sb.append(Messages.FeatureInstallOperation_IdLabel);
sb.append(featureInfo.getId());
if (wantVersions) {
sb.append(Messages.FeatureInstallOperation_VersionLabel);
sb.append(featureInfo.getVersion().toString());
}
sb.append("\n"); //$NON-NLS-1$
}
throw new ProvisionException(sb.toString());
}
monitor.done();
}
private InstallOperation resolve(SubMonitor monitor) throws CoreException {
checkIfCanceled(monitor);
URI[] uris = (URI[]) urisUsed.toArray(new URI[urisUsed.size()]);
InstallOperation installOperation = provisioningUI.getInstallOperation(ius, uris);
IStatus operationStatus = installOperation.resolveModal(monitor);
if (operationStatus.getSeverity() > IStatus.WARNING) {
throw new CoreException(operationStatus);
}
return installOperation;
}
private void checkIfCanceled(IProgressMonitor monitor) {
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
}
}