blob: 34acd48a2df82103b1fed1539f50cb399376be23 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2021 WindRiver Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* WindRiver Corporation - initial API and implementation
* Ericsson AB (Pascal Rapicault) - Bug 387115 - Allow to export everything
*******************************************************************************/
package org.eclipse.equinox.internal.p2.importexport.internal.wizard;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.Properties;
import java.util.concurrent.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.extensionlocation.ExtensionLocationArtifactRepositoryFactory;
import org.eclipse.equinox.internal.p2.extensionlocation.ExtensionLocationMetadataRepositoryFactory;
import org.eclipse.equinox.internal.p2.importexport.internal.Constants;
import org.eclipse.equinox.internal.p2.importexport.internal.Messages;
import org.eclipse.equinox.internal.p2.ui.ProvUI;
import org.eclipse.equinox.internal.p2.ui.dialogs.ISelectableIUsPage;
import org.eclipse.equinox.internal.p2.ui.dialogs.ProvisioningOperationWizard;
import org.eclipse.equinox.internal.p2.ui.model.ProfileElement;
import org.eclipse.equinox.internal.p2.ui.viewers.IUDetailsLabelProvider;
import org.eclipse.equinox.p2.core.*;
import org.eclipse.equinox.p2.engine.*;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
import org.eclipse.equinox.p2.repository.artifact.spi.ArtifactRepositoryFactory;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
import org.eclipse.equinox.p2.repository.metadata.spi.MetadataRepositoryFactory;
import org.eclipse.equinox.p2.ui.ProvisioningUI;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.*;
import org.osgi.util.tracker.ServiceTracker;
public class ImportFromInstallationPage extends AbstractImportPage implements ISelectableIUsPage {
protected IProvisioningAgent otherInstanceAgent = null;
IProfile toBeImportedProfile = null;
private File instancePath = null;
private URI[] metaURIs = null;
private URI[] artiURIs = null;
private IProvisioningAgentProvider agentProvider;
public ImportFromInstallationPage(ProvisioningUI ui, ProvisioningOperationWizard wizard) {
super("importfrominstancepage", ui, wizard); //$NON-NLS-1$
setTitle(Messages.ImportFromInstallationPage_DIALOG_TITLE);
setDescription(Messages.ImportFromInstallationPage_DIALOG_DESCRIPTION);
}
@Override
protected void createContents(Composite composite) {
createDestinationGroup(composite, true);
createInstallationTable(composite);
}
@Override
protected String getDestinationLabel() {
return Messages.ImportFromInstallationPage_DESTINATION_LABEL;
}
@Override
protected String getDialogTitle() {
return Messages.ImportFromInstallationPage_DIALOG_TITLE;
}
@Override
protected Object getInput() {
return new IInstallableUnit[0];
}
@Override
protected String getInvalidDestinationMessage() {
return Messages.ImportFromInstallationPage_INVALID_DESTINATION;
}
@Override
protected String getNoOptionsMessage() {
return Messages.ImportFromInstallationPage_SELECT_COMPONENT;
}
@Override
protected boolean validateDestinationGroup() {
return validateDestinationGroup(new NullProgressMonitor());
}
private IProvisioningAgentProvider getAgentProvider() {
if (agentProvider == null) {
ServiceTracker<IProvisioningAgentProvider, IProvisioningAgentProvider> tracker = new ServiceTracker<>(
Platform.getBundle(Constants.Bundle_ID).getBundleContext(), IProvisioningAgentProvider.class, null);
tracker.open();
agentProvider = tracker.getService();
tracker.close();
}
return agentProvider;
}
boolean validateDestinationGroup(IProgressMonitor monitor) {
SubMonitor progress = SubMonitor.convert(monitor, 100);
boolean rt;
if (Display.findDisplay(Thread.currentThread()) == null) {
Callable<Boolean> getSuperValidateDest = new Callable<>() {
Boolean validated;
@Override
public Boolean call() throws Exception {
Display.getDefault()
.syncExec(() -> validated = ImportFromInstallationPage.super.validateDestinationGroup());
return validated;
}
};
ExecutorService executor = Executors.newSingleThreadScheduledExecutor();
Future<Boolean> getSuperDestTask = executor.submit(getSuperValidateDest);
try {
rt = getSuperDestTask.get().booleanValue();
} catch (Exception e) {
return false;
} finally {
executor.shutdown();
}
} else
rt = super.validateDestinationGroup();
if (rt) {
try {
String destination;
if (Display.findDisplay(Thread.currentThread()) == null) {
Callable<String> getDestinationValue = new Callable<>() {
String des;
@Override
public String call() throws Exception {
if (Display.findDisplay(Thread.currentThread()) == null) {
Display.getDefault().syncExec(() -> des = getDestinationValue());
} else
des = getDestinationValue();
return des;
}
};
ExecutorService executor = Executors.newSingleThreadScheduledExecutor();
Future<String> getDestTask = executor.submit(getDestinationValue);
try {
destination = getDestTask.get();
} finally {
executor.shutdown();
}
} else
destination = getDestinationValue();
String toBeImportedProfileId = null;
try {
File config = new File(destination, "configuration/config.ini"); //$NON-NLS-1$
URI configArea = config.getParentFile().toURI();
InputStream is = null;
// default area
File p2DataArea = new File(destination, "p2"); //$NON-NLS-1$
try {
Properties props = new Properties();
is = new FileInputStream(config);
props.load(is);
toBeImportedProfileId = props.getProperty("eclipse.p2.profile"); //$NON-NLS-1$
String url = props.getProperty("eclipse.p2.data.area"); //$NON-NLS-1$
if (url != null) {
final String CONFIG_DIR = "@config.dir/"; //$NON-NLS-1$
final String FILE_PROTOCOL = "file:"; //$NON-NLS-1$
if (url.startsWith(CONFIG_DIR))
url = FILE_PROTOCOL + url.substring(CONFIG_DIR.length());
p2DataArea = new File(URIUtil.makeAbsolute(URIUtil
.fromString(new File(url.substring(FILE_PROTOCOL.length())).isAbsolute() ? url
: url.substring(FILE_PROTOCOL.length())),
configArea));
}
} catch (IOException ioe) {
// ignore
} finally {
try {
is.close();
} catch (IOException ioe) {
// ignore
}
is = null;
}
if (p2DataArea.exists()) {
boolean createAgent = true;
if (otherInstanceAgent != null) {
// don't create agent again if the selection is not changed
if (!p2DataArea.equals(instancePath)) {
otherInstanceAgent.stop();
otherInstanceAgent = null;
// update cached specified path by users
instancePath = p2DataArea;
cleanLocalRepository();
} else
createAgent = false;
}
if (createAgent)
otherInstanceAgent = getAgentProvider().createAgent(p2DataArea.toURI());
ArtifactRepositoryFactory factory = new ExtensionLocationArtifactRepositoryFactory();
factory.setAgent(agent);
IArtifactRepository artiRepo = factory.load(new File(destination).toURI(), 0,
progress.newChild(50));
artiURIs = new URI[] { artiRepo.getLocation() };
MetadataRepositoryFactory metaFatory = new ExtensionLocationMetadataRepositoryFactory();
metaFatory.setAgent(agent);
IMetadataRepository metaRepo = metaFatory.load(new File(destination).toURI(), 0,
progress.newChild(50));
metaURIs = new URI[] { metaRepo.getLocation() };
} else
throw new FileNotFoundException();
} catch (ProvisionException e) {
if (otherInstanceAgent != null) {
toBeImportedProfile = null;
IMetadataRepositoryManager manager = agent.getService(IMetadataRepositoryManager.class);
IArtifactRepositoryManager artifactManager = agent.getService(IArtifactRepositoryManager.class);
IProfileRegistry registry = otherInstanceAgent.getService(IProfileRegistry.class);
if (toBeImportedProfileId != null)
toBeImportedProfile = registry.getProfile(toBeImportedProfileId);
if (toBeImportedProfile == null) {
IProfile[] existingProfiles = registry.getProfiles();
if (existingProfiles.length == 1) {
toBeImportedProfile = existingProfiles[0];
} else {
for (IProfile existingProfile : existingProfiles) {
if (toBeImportedProfile == null)
toBeImportedProfile = existingProfile;
else if ((toBeImportedProfile.getTimestamp() < existingProfile.getTimestamp())) // assuming
// last
// modified
// one
// is
// we
// are
// looking
// for
toBeImportedProfile = existingProfile;
}
}
}
IAgentLocation location = otherInstanceAgent.getService(IAgentLocation.class);
URI engineDataArea = location.getDataArea("org.eclipse.equinox.p2.engine"); //$NON-NLS-1$
progress.setWorkRemaining(50);
IMetadataRepository metaRepo = manager.loadRepository(
engineDataArea
.resolve("profileRegistry/" + toBeImportedProfile.getProfileId() + ".profile"), //$NON-NLS-1$//$NON-NLS-2$
progress.newChild(25));
metaURIs = new URI[] { metaRepo.getLocation() };
IArtifactRepository artiRepo = artifactManager.loadRepository(new File(destination).toURI(),
progress.newChild(25));
artiURIs = new URI[] { artiRepo.getLocation() };
} else
throw new Exception();
}
} catch (Exception e) {
Display.getDefault().asyncExec(() -> setErrorMessage(getInvalidDestinationMessage()));
rt = false;
if (otherInstanceAgent != null)
otherInstanceAgent.stop();
otherInstanceAgent = null;
toBeImportedProfile = null;
cleanLocalRepository();
} finally {
monitor.done();
}
}
return rt;
}
@Override
protected void giveFocusToDestination() {
destinationBrowseButton.setFocus();
}
@Override
protected void handleDestinationBrowseButtonPressed() {
DirectoryDialog dialog = new DirectoryDialog(getContainer().getShell());
dialog.setText(getDialogTitle());
dialog.setFilterPath(getDestinationValue());
final String selectedFileName = dialog.open();
if (selectedFileName != null) {
modifyDestinationValue(selectedFileName);
handleDestinationChanged(selectedFileName);
}
}
@Override
protected void handleDestinationChanged(String newDestination) {
try {
getContainer().run(true, false, monitor -> {
Object input = null;
if (validateDestinationGroup(monitor)) {
final IProfile currentProfile = toBeImportedProfile;
final ProfileElement element = new ProfileElement(null, currentProfile.getProfileId()) {
@Override
public org.eclipse.equinox.p2.query.IQueryable<?> getQueryable() {
return currentProfile;
}
};
element.setQueryable(currentProfile);
input = element;
}
final Object viewerInput = input;
Display.getDefault().asyncExec(() -> {
viewer.setInput(viewerInput);
updatePageCompletion();
});
});
} catch (InvocationTargetException e) {
setErrorMessage(e.getLocalizedMessage());
setPageComplete(false);
} catch (InterruptedException e) {
// won't happen
}
}
@Override
void modifyDestinationValue(String selectedFileName) {
/*
* If the destination file is a Mac app bundle, modify the destination to
* *.app/Contents/Eclipse if the path exists.
*/
if ("cocoa".equals(SWT.getPlatform())) { //$NON-NLS-1$
Path nPath = new Path(selectedFileName);
if (nPath.lastSegment().endsWith(".app")) { //$NON-NLS-1$
IPath appendedPath = nPath.append("Contents").append("Eclipse");//$NON-NLS-1$ //$NON-NLS-2$
if (appendedPath.toFile().exists()) {
selectedFileName = appendedPath.toOSString();
}
}
}
setDestinationValue(selectedFileName);
}
@Override
protected boolean validDestination() {
if (this.destinationNameField == null)
return true;
File file = new File(getDestinationValue());
return file.exists() && file.isDirectory();
}
class ImportFromInstallationLabelProvider extends IUDetailsLabelProvider {
@Override
public String getColumnText(Object element, int columnIndex) {
String text = super.getColumnText(element, columnIndex);
// it's the order of label provider
if (columnIndex == 0) {
IInstallableUnit iu = ProvUI.getAdapter(element, IInstallableUnit.class);
return getIUNameWithDetail(iu);
}
return text;
}
@Override
public Color getForeground(Object element) {
IInstallableUnit iu = ProvUI.getAdapter(element, IInstallableUnit.class);
if (hasInstalled(iu))
return Display.getDefault().getSystemColor(SWT.COLOR_GRAY);
return super.getForeground(element);
}
}
@Override
protected ITableLabelProvider getLabelProvider() {
return new ImportFromInstallationLabelProvider();
}
@Override
public void dispose() {
super.dispose();
if (otherInstanceAgent != null) {
otherInstanceAgent.stop();
otherInstanceAgent = null;
toBeImportedProfile = null;
}
if (getWizard().performCancel())
cleanLocalRepository();
}
public void cleanLocalRepository() {
if (metaURIs != null && metaURIs.length > 0) {
IProvisioningAgent runningAgent = getProvisioningUI().getSession().getProvisioningAgent();
IMetadataRepositoryManager manager = runningAgent.getService(IMetadataRepositoryManager.class);
for (URI uri : metaURIs)
manager.removeRepository(uri);
IArtifactRepositoryManager artifactManager = runningAgent.getService(IArtifactRepositoryManager.class);
for (URI uri : artiURIs)
artifactManager.removeRepository(uri);
}
}
@Override
public Object[] getCheckedIUElements() {
return viewer.getCheckedElements();
}
@Override
public Object[] getSelectedIUElements() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setCheckedElements(Object[] elements) {
throw new UnsupportedOperationException();
}
public ProvisioningContext getProvisioningContext() {
ProvisioningContext context = new ProvisioningContext(getProvisioningUI().getSession().getProvisioningAgent());
context.setArtifactRepositories(artiURIs);
context.setMetadataRepositories(metaURIs);
return context;
}
}