core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/p2/DynamicP2Installer.java
Updated the dynamic p2 installer to improve progress reporting and check for cancel during install.
/*
* 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.
*
*/
package com.nokia.carbide.internal.discovery.ui.p2;
import java.io.File;
import java.io.FileNotFoundException;
import java.net.URI;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.equinox.internal.provisional.p2.director.IDirector;
import org.eclipse.equinox.internal.provisional.p2.director.ProfileChangeRequest;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.engine.IProfile;
import org.eclipse.equinox.p2.engine.IProfileRegistry;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.query.QueryUtil;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.equinox.p2.ui.ProvisioningUI;
import com.nokia.carbide.discovery.ui.Activator;
/**
* Installer to install features from a p2 repository at a supplied URL or directory.
*
* The supplied directory should have as sub-directories features and plugins. These
* sub-directories in turn can contain any number of features and their corresponding
* plug-ins.
*
* <p/>
* e.g.
* <p/>
* <pre>
* <Feature Directory>
* |
* | --- artifacts.jar
* | --- content.jar
* |
* ----<features>
* |
* |----<feature folder name>
* |
* |---features.xml file (contains list of feature jars)
* ----<plugins>
* |
* ---jar files;
* </pre>
*/
@SuppressWarnings("restriction")
public class DynamicP2Installer {
private IPath repositoryLocation;
private ProvisioningUI provisioningUI;
private IProvisioningAgent agent;
private IProfile profile;
/**
* Performs the install.
* @param monitor An implementation of IProgressMonitor, usually showing the
* installation progress as a Progress Bar to the user.
*/
public static IStatus install(File repositoryDirectory, IProgressMonitor monitor) {
try {
DynamicP2Installer installer = new DynamicP2Installer(repositoryDirectory);
installer.doInstall(monitor);
return Status.OK_STATUS;
} catch (CoreException e) {
return e.getStatus();
} catch (FileNotFoundException e) {
return Activator.makeErrorStatus(null, e);
}
}
private DynamicP2Installer(File repositoryDirectory) throws FileNotFoundException {
checkRepository(repositoryDirectory);
repositoryLocation = new Path(repositoryDirectory.getAbsolutePath());
provisioningUI = ProvisioningUI.getDefaultUI();
agent = provisioningUI.getSession().getProvisioningAgent();
profile = getProfile();
}
private void checkRepository(File repositoryDirectory) throws FileNotFoundException {
if (!repositoryDirectory.isDirectory()) {
throw new FileNotFoundException(repositoryDirectory + " is not a directory.");
}
if (!(new File(repositoryDirectory, "features").isDirectory())) {
throw new FileNotFoundException(repositoryDirectory + " missing \"features\" directory.");
}
if (!(new File(repositoryDirectory, "plugins").isDirectory())) {
throw new FileNotFoundException(repositoryDirectory + " missing \"plugins\" directory.");
}
if (!(new File(repositoryDirectory, "artifacts.jar").exists()) && !(new File(repositoryDirectory, "artifacts.xml").exists())) {
throw new FileNotFoundException(repositoryDirectory + " missing artifacts.jar.");
}
if (!(new File(repositoryDirectory, "content.jar").exists()) && !(new File(repositoryDirectory, "content.xml").exists())) {
throw new FileNotFoundException(repositoryDirectory + " missing content.jar.");
}
}
private void doInstall(IProgressMonitor monitor) throws CoreException {
SubMonitor subMonitor = SubMonitor.convert(monitor, "Installing plugins from " + repositoryLocation.toOSString(), 100);
URI uri = URIUtil.toURI(repositoryLocation);
IMetadataRepositoryManager metadataRepoManager =
(IMetadataRepositoryManager) agent.getService(IMetadataRepositoryManager.SERVICE_NAME);
IArtifactRepositoryManager artifactRepoManager =
(IArtifactRepositoryManager) agent.getService(IArtifactRepositoryManager.SERVICE_NAME);
try {
// add and load repository
checkIfCanceled(subMonitor);
metadataRepoManager.addRepository(uri);
IMetadataRepository metadataRepository = metadataRepoManager.loadRepository(uri, null);
artifactRepoManager.addRepository(uri);
artifactRepoManager.loadRepository(uri, null);
subMonitor.worked(10);
// get IU from repository
checkIfCanceled(subMonitor);
IQueryResult<IInstallableUnit> units = metadataRepository.query(QueryUtil.createIUGroupQuery(), subMonitor);
if (units.isEmpty())
throw new CoreException(Activator.makeErrorStatus("Could not find installable unit", null));
subMonitor.worked(10);
// check if installed
checkIfCanceled(subMonitor);
IQueryResult<IInstallableUnit> result = profile.query(QueryUtil.createIUQuery(units.iterator().next()), subMonitor);
if (!result.isEmpty())
throw new CoreException(Activator.makeStatus(IStatus.CANCEL, null, null)); // already installed
subMonitor.worked(10);
// do provisioning operation
checkIfCanceled(subMonitor);
ProfileChangeRequest request = new ProfileChangeRequest(profile);
request.addAll(units.toUnmodifiableSet());
IDirector director = (IDirector) agent.getService(IDirector.SERVICE_NAME);
IStatus status = director.provision(request, null, subMonitor);
subMonitor.worked(70);
if (!status.isOK())
throw new CoreException(status);
}
finally {
metadataRepoManager.removeRepository(uri);
artifactRepoManager.removeRepository(uri);
subMonitor.done();
}
}
private IProfile getProfile() {
IProfileRegistry profileRegistry = (IProfileRegistry) agent.getService(IProfileRegistry.SERVICE_NAME);
return profileRegistry.getProfile(provisioningUI.getProfileId());
}
private void checkIfCanceled(IProgressMonitor monitor) throws CoreException {
if (monitor.isCanceled()) {
throw new CoreException(Activator.makeStatus(IStatus.CANCEL, null, null)); // installation canceled
}
}
}