blob: a152078b2f332cee6615b359e150f834eb1b3fcb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2013 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
* Yatta Solutions - news (bug 401721), public API (bug 432803)
* JBoss (Pascal Rapicault) - Bug 406907 - Add p2 remediation page to MPC install flow
*******************************************************************************/
package org.eclipse.epp.internal.mpc.ui.wizards;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
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.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.epp.internal.mpc.core.MarketplaceClientCore;
import org.eclipse.epp.internal.mpc.core.model.News;
import org.eclipse.epp.internal.mpc.ui.CatalogRegistry;
import org.eclipse.epp.internal.mpc.ui.MarketplaceClientUi;
import org.eclipse.epp.internal.mpc.ui.MarketplaceClientUiPlugin;
import org.eclipse.epp.internal.mpc.ui.catalog.MarketplaceCatalog;
import org.eclipse.epp.internal.mpc.ui.catalog.MarketplaceDiscoveryStrategy;
import org.eclipse.epp.internal.mpc.ui.commands.MarketplaceWizardCommand;
import org.eclipse.epp.internal.mpc.ui.operations.AbstractProvisioningOperation;
import org.eclipse.epp.internal.mpc.ui.operations.ProfileChangeOperationComputer;
import org.eclipse.epp.internal.mpc.ui.operations.ProfileChangeOperationComputer.OperationType;
import org.eclipse.epp.internal.mpc.ui.wizards.MarketplaceViewer.ContentType;
import org.eclipse.epp.internal.mpc.ui.wizards.SelectionModel.CatalogItemEntry;
import org.eclipse.epp.internal.mpc.ui.wizards.SelectionModel.FeatureEntry;
import org.eclipse.epp.mpc.core.model.ICategory;
import org.eclipse.epp.mpc.core.model.IMarket;
import org.eclipse.epp.mpc.core.model.INews;
import org.eclipse.epp.mpc.core.model.INode;
import org.eclipse.epp.mpc.ui.CatalogDescriptor;
import org.eclipse.epp.mpc.ui.MarketplaceUrlHandler;
import org.eclipse.epp.mpc.ui.Operation;
import org.eclipse.equinox.internal.p2.discovery.AbstractDiscoveryStrategy;
import org.eclipse.equinox.internal.p2.discovery.model.CatalogItem;
import org.eclipse.equinox.internal.p2.ui.ProvUI;
import org.eclipse.equinox.internal.p2.ui.discovery.util.WorkbenchUtil;
import org.eclipse.equinox.internal.p2.ui.discovery.wizards.DiscoveryWizard;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.operations.ProfileChangeOperation;
import org.eclipse.equinox.p2.operations.ProvisioningJob;
import org.eclipse.equinox.p2.operations.RemediationOperation;
import org.eclipse.equinox.p2.operations.UninstallOperation;
import org.eclipse.equinox.p2.ui.AcceptLicensesWizardPage;
import org.eclipse.equinox.p2.ui.ProvisioningUI;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.wizard.IWizardContainer;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWebBrowser;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
import org.eclipse.ui.internal.browser.WorkbenchBrowserSupport;
import org.eclipse.ui.statushandlers.StatusManager;
/**
* A wizard for interacting with a marketplace service.
*
* @author David Green
* @author Carsten Reckord
*/
public class MarketplaceWizard extends DiscoveryWizard implements InstallProfile, IMarketplaceWebBrowser {
private static final String PREF_DEFAULT_CATALOG = CatalogDescriptor.class.getSimpleName();
private static final String DEBUG_NEWS_FLAG = MarketplaceClientUi.BUNDLE_ID + "/news/debug"; //$NON-NLS-1$
private static final String DEBUG_NEWS_TITLE = MarketplaceClientUi.BUNDLE_ID + "/news/title"; //$NON-NLS-1$
private static final String DEBUG_NEWS_URL = MarketplaceClientUi.BUNDLE_ID + "/news/url"; //$NON-NLS-1$
public static class WizardState {
private ContentType contentType;
private Set<INode> content;
private IMarket filterMarket;
private ICategory filterCategory;
private String filterQuery;
private Boolean proceedWithInstallation;
public ContentType getContentType() {
return contentType;
}
public void setContentType(ContentType contentType) {
this.contentType = contentType;
}
public Set<INode> getContent() {
return content;
}
public void setContent(Set<INode> content) {
this.content = content;
}
public IMarket getFilterMarket() {
return filterMarket;
}
public void setFilterMarket(IMarket filterMarket) {
this.filterMarket = filterMarket;
}
public ICategory getFilterCategory() {
return filterCategory;
}
public void setFilterCategory(ICategory filterCategory) {
this.filterCategory = filterCategory;
}
public String getFilterQuery() {
return filterQuery;
}
public void setFilterQuery(String filterQuery) {
this.filterQuery = filterQuery;
}
public Boolean getProceedWithInstallation() {
return proceedWithInstallation;
}
public void setProceedWithInstallation(Boolean proceedWithInstallation) {
this.proceedWithInstallation = proceedWithInstallation;
}
}
private Set<String> installedFeatures;
private SelectionModel selectionModel;
private MarketplaceBrowserIntegration browserListener;
private ProfileChangeOperation profileChangeOperation;
private FeatureSelectionWizardPage featureSelectionWizardPage;
private AcceptLicensesWizardPage acceptLicensesPage;
private IInstallableUnit[] operationIUs;
private Set<CatalogItem> operationNewInstallItems;
private boolean initialSelectionInitialized;
private Set<URI> addedRepositoryLocations;
private boolean withRemediation;
private String errorMessage;
private WizardState initialState;
public String getErrorMessage() {
return errorMessage;
}
public MarketplaceWizard(MarketplaceCatalog catalog, MarketplaceCatalogConfiguration configuration) {
super(catalog, configuration);
setWindowTitle(Messages.MarketplaceWizard_eclipseSolutionCatalogs);
createSelectionModel();
withRemediation = true;
String withRemediationOverride = System.getProperty("marketplace.remediation.enabled"); //$NON-NLS-1$
if (withRemediationOverride != null) {
withRemediation = Boolean.parseBoolean(withRemediationOverride);
}
}
private void createSelectionModel() {
selectionModel = new SelectionModel(this) {
@Override
public void selectionChanged() {
super.selectionChanged();
profileChangeOperation = null;
}
};
}
@Override
public MarketplaceCatalogConfiguration getConfiguration() {
return (MarketplaceCatalogConfiguration) super.getConfiguration();
}
@Override
public MarketplaceCatalog getCatalog() {
return (MarketplaceCatalog) super.getCatalog();
}
@Override
protected MarketplacePage doCreateCatalogPage() {
return new MarketplacePage(getCatalog(), getConfiguration());
}
public ProfileChangeOperation getProfileChangeOperation() {
return profileChangeOperation;
}
public void setProfileChangeOperation(ProfileChangeOperation profileChangeOperation) {
this.profileChangeOperation = profileChangeOperation;
}
void initializeInitialSelection() throws CoreException {
if (!wantInitializeInitialSelection()) {
throw new IllegalStateException();
}
initialSelectionInitialized = true;
initializeCatalog();
if (getConfiguration().getInitialState() != null || getConfiguration().getInitialOperations() != null) {
try {
getContainer().run(true, true, new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
new SelectionModelStateSerializer(getCatalog(), getSelectionModel()).deserialize(
getConfiguration().getInitialState(), getConfiguration().getInitialOperations(),
monitor);
}
});
} catch (InvocationTargetException e) {
throw new CoreException(MarketplaceClientCore.computeStatus(e, Messages.MarketplaceViewer_unexpectedException));
} catch (InterruptedException e) {
// user canceled
throw new CoreException(Status.CANCEL_STATUS);
}
List<Entry<CatalogItem, Operation>> itemToSelectedOperation = new ArrayList<Entry<CatalogItem, Operation>>(
getSelectionModel().getItemToSelectedOperation().entrySet());
final List<CatalogItem> noninstallableItems = new ArrayList<CatalogItem>();
for (Entry<CatalogItem, Operation> entry : itemToSelectedOperation) {
if (entry.getValue() != Operation.NONE) {
boolean unavailableInstall = (Boolean.FALSE.equals(entry.getKey().getAvailable()) || entry.getKey()
.getSiteUrl() == null)
&& (entry.getValue() == Operation.INSTALL || entry.getValue() == Operation.UPDATE);
if (unavailableInstall) {
getSelectionModel().select(entry.getKey(), Operation.NONE);
noninstallableItems.add(entry.getKey());
} else {
entry.getKey().setSelected(true);
}
}
}
if (!noninstallableItems.isEmpty()) {
notifyNonInstallableItems(noninstallableItems);
}
}
}
protected void notifyNonInstallableItems(final List<CatalogItem> noninstallableItems) {
MessageDialog dialog = new MessageDialog(getShell(), Messages.MarketplaceWizard_UnableToInstallSolutions, null, Messages.MarketplaceWizard_IncompatibleSolutionsMessage, MessageDialog.ERROR,
new String[] { IDialogConstants.OK_LABEL }, 0) {
@Override
protected Control createCustomArea(Composite parent) {
parent.setLayout(new GridLayout());
TableViewer tableViewer = new TableViewer(parent, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL
| SWT.BORDER);
tableViewer.setLabelProvider(createLabelProvider());
tableViewer.setContentProvider(createContentProvider());
tableViewer.setInput(noninstallableItems);
Control tableControl = tableViewer.getControl();
GridDataFactory.fillDefaults()
.grab(true, true)
.align(SWT.FILL, SWT.FILL)
.hint(SWT.DEFAULT,
Math.max(40,
Math.min(120, tableControl.computeSize(SWT.DEFAULT, SWT.DEFAULT).y)))
.applyTo(tableControl);
return tableControl;
}
private LabelProvider createLabelProvider() {
return new LabelProvider() {
@Override
public String getText(Object element) {
//TODO it would be great to know the compatible version range
//we could show that with an IStyledLabelProvider behind the name
return ((CatalogItem) element).getName();
}
@Override
public Image getImage(Object element) {
return MarketplaceClientUiPlugin.getInstance()
.getImageRegistry()
.get(MarketplaceClientUiPlugin.IU_ICON_ERROR);
}
};
}
private IStructuredContentProvider createContentProvider() {
return new IStructuredContentProvider() {
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
public void dispose() {
}
public Object[] getElements(Object inputElement) {
return ((List<?>) inputElement).toArray();
}
};
}
};
dialog.open();
}
boolean wantInitializeInitialSelection() {
if (initialSelectionInitialized) {
return false;
} else if (getConfiguration().getInitialState() != null || getConfiguration().getInitialOperations() != null) {
return true;
} else if (initialState != null) {
WizardState initialState = getInitialState();
if ((initialState.getContent() != null && !initialState.getContent().isEmpty())
|| (initialState.getContentType() != null && initialState.getContentType() != ContentType.SEARCH)
|| (initialState.getFilterCategory() != null || initialState.getFilterMarket() != null || initialState.getFilterQuery() != null)) {
return true;
}
}
return false;
}
@Override
public boolean canFinish() {
if (computeMustCheckLicenseAcceptance()) {
if (acceptLicensesPage == null && getContainer().getCurrentPage() == getFeatureSelectionWizardPage()) {
getNextPage(getFeatureSelectionWizardPage(), false);
}
if (acceptLicensesPage == null || !acceptLicensesPage.isPageComplete()) {
return false;
}
}
if (profileChangeOperation != null) {
IStatus resolutionResult = profileChangeOperation.getResolutionResult();
switch (resolutionResult.getSeverity()) {
case IStatus.OK:
case IStatus.WARNING:
case IStatus.INFO:
return true;
}
}
return false;
}
@Override
public IWizardPage getNextPage(IWizardPage page) {
return getNextPage(page, true);
}
IWizardPage getNextPage(IWizardPage page, boolean nextpressed) {
boolean skipFeatureSelection = false;
MarketplacePage catalogPage = getCatalogPage();
if (page == catalogPage && nextpressed) {
profileChangeOperation = null;
featureSelectionWizardPage.updateMessage();
if (catalogPage.canSkipFeatureSelection()) {
skipFeatureSelection = true;
}
}
if (page == featureSelectionWizardPage || (page == catalogPage && skipFeatureSelection)) {
if (nextpressed && profileChangeOperation != null
&& profileChangeOperation instanceof RemediationOperation) {
try {
getContainer().run(true, false, new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) {
((RemediationOperation) profileChangeOperation).setCurrentRemedy(featureSelectionWizardPage.getRemediationGroup()
.getCurrentRemedy());
profileChangeOperation.resolveModal(monitor);
}
});
} catch (InterruptedException e) {
// Nothing to report if thread was interrupted
} catch (InvocationTargetException e) {
ProvUI.handleException(e.getCause(), null, StatusManager.SHOW | StatusManager.LOG);
}
}
IWizardPage nextPage = null;
boolean operationUpdated = false;
if (profileChangeOperation == null) {
if (nextpressed) {
updateProfileChangeOperation();
operationUpdated = true;
}
if (profileChangeOperation == null || !profileChangeOperation.getResolutionResult().isOK()) {
// can't compute a change operation, so there must be some kind of error
// we show these on the the feature selection wizard page
nextPage = featureSelectionWizardPage;
} else if (profileChangeOperation instanceof UninstallOperation) {
// next button was used to resolve errors on an uninstall.
// by returning the same page the finish button will be enabled, allowing the user to finish.
nextPage = featureSelectionWizardPage;
} else if (profileChangeOperation instanceof RemediationOperation) {
nextPage = featureSelectionWizardPage;
}
}
if (nextPage == null && nextpressed && profileChangeOperation instanceof RemediationOperation
&& !featureSelectionWizardPage.isInRemediationMode()) {
featureSelectionWizardPage.flipToRemediationComposite();
nextPage = featureSelectionWizardPage;
}
if (nextPage == null && computeMustCheckLicenseAcceptance()) {
if (acceptLicensesPage == null) {
acceptLicensesPage = new AcceptLicensesWizardPage(
ProvisioningUI.getDefaultUI().getLicenseManager(), operationIUs, profileChangeOperation);
addPage(acceptLicensesPage);
} else {
acceptLicensesPage.update(operationIUs, profileChangeOperation);
}
if (nextpressed || acceptLicensesPage.hasLicensesToAccept()
|| profileChangeOperation instanceof RemediationOperation) {
nextPage = acceptLicensesPage;
}
}
if (nextPage == null && page == catalogPage) {
nextPage = featureSelectionWizardPage;
}
if (operationUpdated && nextPage == getContainer().getCurrentPage()) {
getContainer().updateButtons();
}
return nextPage;
}
if (page instanceof ImportFavoritesPage) {
return catalogPage;
}
return getNextPageInList(page);
}
protected IWizardPage getNextPageInList(IWizardPage page) {
return super.getNextPage(page);
}
public boolean computeMustCheckLicenseAcceptance() {
return profileChangeOperation != null && !(profileChangeOperation instanceof UninstallOperation);
}
@Override
public void addPages() {
doDefaultCatalogSelection();
super.addPages();
featureSelectionWizardPage = new FeatureSelectionWizardPage();
addPage(featureSelectionWizardPage);
}
FeatureSelectionWizardPage getFeatureSelectionWizardPage() {
return featureSelectionWizardPage;
}
@Override
public IWizardPage getStartingPage() {
if (getConfiguration().getCatalogDescriptor() != null) {
if (wantInitializeInitialSelection()) {
WizardState initialState = getInitialState();
if (initialState == null || !Boolean.FALSE.equals(initialState.getProceedWithInstallation())) {
return getFeatureSelectionWizardPage();
}
}
return getCatalogPage();
}
return super.getStartingPage();
}
private void doDefaultCatalogSelection() {
if (getConfiguration().getCatalogDescriptor() == null) {
String defaultCatalogUrl = MarketplaceClientUiPlugin.getInstance()
.getPreferenceStore()
.getString(PREF_DEFAULT_CATALOG);
// if a preferences was set, we default to that catalog descriptor
if (defaultCatalogUrl != null && defaultCatalogUrl.length() > 0) {
for (CatalogDescriptor descriptor : getConfiguration().getCatalogDescriptors()) {
URL url = descriptor.getUrl();
try {
if (url.toURI().toString().equals(defaultCatalogUrl)) {
getConfiguration().setCatalogDescriptor(descriptor);
break;
}
} catch (URISyntaxException e) {
// ignore
}
}
}
// if no catalog is selected, pick one
if (getConfiguration().getCatalogDescriptor() == null
&& getConfiguration().getCatalogDescriptors().size() > 0) {
// fall back to first catalog
getConfiguration().setCatalogDescriptor(getConfiguration().getCatalogDescriptors().get(0));
}
}
}
@Override
public void dispose() {
removeAddedRepositoryLocations();
if (getConfiguration().getCatalogDescriptor() != null) {
// remember the catalog for next time.
try {
MarketplaceClientUiPlugin.getInstance()
.getPreferenceStore()
.setValue(PREF_DEFAULT_CATALOG,
getConfiguration().getCatalogDescriptor().getUrl().toURI().toString());
} catch (URISyntaxException e) {
// ignore
}
}
if (getCatalog() != null) {
getCatalog().dispose();
}
super.dispose();
}
@Override
public boolean performFinish() {
if (profileChangeOperation != null
&& profileChangeOperation.getResolutionResult().getSeverity() != IStatus.ERROR) {
if (computeMustCheckLicenseAcceptance()) {
if (acceptLicensesPage != null && acceptLicensesPage.isPageComplete()) {
acceptLicensesPage.performFinish();
}
}
ProvisioningJob provisioningJob = profileChangeOperation.getProvisioningJob(null);
if (provisioningJob != null) {
if (!operationNewInstallItems.isEmpty()) {
provisioningJob.addJobChangeListener(new ProvisioningJobListener(operationNewInstallItems));
}
ProvisioningUI.getDefaultUI().schedule(provisioningJob, StatusManager.SHOW | StatusManager.LOG);
addedRepositoryLocations = null;
return true;
}
}
return false;
}
@Override
public MarketplacePage getCatalogPage() {
return (MarketplacePage) super.getCatalogPage();
}
public synchronized Set<String> getInstalledFeatures() {
if (installedFeatures == null) {
try {
if (Display.getCurrent() != null) {
getContainer().run(true, false, new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException,
InterruptedException {
installedFeatures = MarketplaceClientUi.computeInstalledFeatures(monitor);
}
});
} else {
installedFeatures = MarketplaceClientUi.computeInstalledFeatures(new NullProgressMonitor());
}
} catch (InvocationTargetException e) {
MarketplaceClientUi.error(e.getCause());
installedFeatures = Collections.emptySet();
} catch (InterruptedException e) {
// should never happen (not cancelable)
throw new IllegalStateException(e);
}
}
return installedFeatures;
}
public SelectionModel getSelectionModel() {
return selectionModel;
}
public void openUrl(String url) {
String catalogUrl = getCatalogUrl();
if (WorkbenchBrowserSupport.getInstance().isInternalWebBrowserAvailable()
&& url.toLowerCase().startsWith(catalogUrl.toLowerCase())) {
int style = IWorkbenchBrowserSupport.AS_EDITOR | IWorkbenchBrowserSupport.LOCATION_BAR
| IWorkbenchBrowserSupport.NAVIGATION_BAR;
String browserId = "MPC-" + catalogUrl.replaceAll("[^a-zA-Z0-9_-]", "_"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
try {
CatalogDescriptor catalogDescriptor = getConfiguration().getCatalogDescriptor();
IWebBrowser browser = WorkbenchBrowserSupport.getInstance().createBrowser(style, browserId,
catalogDescriptor.getLabel(), catalogDescriptor.getDescription());
final String originalUrl = url;
url = appendWizardState(url);
browser.openURL(new URL(url)); // ORDER DEPENDENCY //don't encode/validate URL - browser can be quite lenient
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().setActive();
if (!hookLocationListener(browser)) { // ORDER DEPENDENCY
browser.openURL(new URL(originalUrl));
}
} catch (PartInitException e) {
MarketplaceClientUi.handle(e.getStatus(),
StatusManager.SHOW | StatusManager.BLOCK | StatusManager.LOG);
} catch (MalformedURLException e) {
IStatus status = new Status(IStatus.ERROR, MarketplaceClientUi.BUNDLE_ID, NLS.bind(
Messages.MarketplaceWizard_cannotOpenUrl, new Object[] { url, e.getMessage() }), e);
MarketplaceClientUi.handle(status, StatusManager.SHOW | StatusManager.BLOCK | StatusManager.LOG);
}
} else {
WorkbenchUtil.openUrl(url, IWorkbenchBrowserSupport.AS_EXTERNAL);
}
}
private String getCatalogUrl() {
CatalogDescriptor catalogDescriptor = getConfiguration().getCatalogDescriptor();
URL catalogUrl = catalogDescriptor.getUrl();
URI catalogUri;
try {
catalogUri = catalogUrl.toURI();
} catch (URISyntaxException e) {
// should never happen
throw new IllegalStateException(e);
}
return catalogUri.toString();
}
private String appendWizardState(String url) {
try {
if (url.indexOf('?') == -1) {
url += '?';
} else {
url += '&';
}
String state = new SelectionModelStateSerializer(getCatalog(), getSelectionModel()).serialize();
url += "mpc=true&mpc_state=" + URLEncoder.encode(state, "UTF-8"); //$NON-NLS-1$//$NON-NLS-2$
return url;
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException(e); // should never happen
}
}
private boolean hookLocationListener(IWebBrowser webBrowser) {
try {
Field partField = findField(webBrowser.getClass(), "part", IWorkbenchPart.class); //$NON-NLS-1$
if (partField != null) {
partField.setAccessible(true);
IWorkbenchPart part = (IWorkbenchPart) partField.get(webBrowser);
if (part != null) {
Field browserViewerField = findField(part.getClass(), "webBrowser", null); //$NON-NLS-1$
if (browserViewerField != null) {
browserViewerField.setAccessible(true);
Object browserViewer = browserViewerField.get(part);
if (browserViewer != null) {
Field browserField = findField(browserViewer.getClass(), "browser", Browser.class); //$NON-NLS-1$
if (browserField != null) {
browserField.setAccessible(true);
Browser browser = (Browser) browserField.get(browserViewer);
if (browser != null) {
// only hook the listener once
if (browser.getData(MarketplaceBrowserIntegration.class.getName()) == null) {
if (browserListener == null) {
browserListener = new MarketplaceBrowserIntegration();
}
browser.setData(MarketplaceBrowserIntegration.class.getName(), browserListener);
// hook in listeners
browser.addLocationListener(browserListener);
browser.addOpenWindowListener(browserListener);
}
return true;
}
}
}
}
}
}
} catch (Throwable t) {
// ignore
}
return false;
}
private Field findField(Class<?> clazz, String fieldName, Class<?> fieldClass) {
while (clazz != Object.class) {
for (Field field : clazz.getDeclaredFields()) {
if (field.getName().equals(fieldName)
&& (fieldClass == null || fieldClass.isAssignableFrom(field.getType()))) {
return field;
}
}
clazz = clazz.getSuperclass();
}
return null;
}
public void updateProfileChangeOperation() {
removeAddedRepositoryLocations();
addedRepositoryLocations = null;
profileChangeOperation = null;
operationIUs = null;
IWizardContainer wizardContainer = getContainer();
if (getSelectionModel().computeProvisioningOperationViable()) {
ProfileChangeOperationComputer provisioningOperation = null;
try {
final Map<CatalogItem, Operation> itemToOperation = getSelectionModel().getItemToSelectedOperation();
final Set<CatalogItem> selectedItems = getSelectionModel().getSelectedCatalogItems();
OperationType operationType = null;
for (Map.Entry<CatalogItem, Operation> entry : itemToOperation.entrySet()) {
if (!selectedItems.contains(entry.getKey())) {
continue;
}
OperationType entryOperationType = OperationType.map(entry.getValue());
if (entryOperationType != null) {
if (operationType == null || operationType == OperationType.UPDATE || entryOperationType == OperationType.CHANGE) {
operationType = entryOperationType;
}
}
}
Map<FeatureEntry, Operation> featureEntries = getSelectionModel().getFeatureEntryToOperation(false,
false);
if (operationType == OperationType.CHANGE || operationType == OperationType.UPDATE) {
Set<OperationType> featureOperations = EnumSet.noneOf(OperationType.class);
for (Entry<FeatureEntry, Operation> entry : featureEntries.entrySet()) {
OperationType operation = OperationType.map(entry.getValue());
if (operation != null) {
featureOperations.add(operation);
}
}
if (featureOperations.contains(OperationType.INSTALL)
&& featureOperations.contains(OperationType.UPDATE)) {
//just perform install instead, which covers update
featureOperations.remove(OperationType.UPDATE);
}
if (featureOperations.size() == 1) {
operationType = featureOperations.iterator().next();
}
}
URI dependenciesRepository = null;
if (getConfiguration().getCatalogDescriptor().getDependenciesRepository() != null) {
try {
dependenciesRepository = getConfiguration().getCatalogDescriptor()
.getDependenciesRepository()
.toURI();
} catch (URISyntaxException e) {
throw new InvocationTargetException(e);
}
}
provisioningOperation = new ProfileChangeOperationComputer(
operationType,
selectedItems,
featureEntries.keySet(),
dependenciesRepository,
getConfiguration().getCatalogDescriptor().isInstallFromAllRepositories() ? ProfileChangeOperationComputer.ResolutionStrategy.FALLBACK_STRATEGY
: ProfileChangeOperationComputer.ResolutionStrategy.SELECTED_REPOSITORIES,
withRemediation);
wizardContainer.run(true, true, provisioningOperation);
profileChangeOperation = provisioningOperation.getOperation();
operationIUs = provisioningOperation.getIus();
addedRepositoryLocations = provisioningOperation.getAddedRepositoryLocations();
operationNewInstallItems = computeNewInstallCatalogItems();
errorMessage = provisioningOperation.getErrorMessage();
final IStatus result = profileChangeOperation.getResolutionResult();
if (result != null && operationIUs != null && operationIUs.length > 0
&& operationType == OperationType.INSTALL) {
switch (result.getSeverity()) {
case IStatus.ERROR:
Job job = new Job(Messages.MarketplaceWizard_errorNotificationJob) {
IStatus r = result;
Set<CatalogItem> items = new HashSet<CatalogItem>(itemToOperation.keySet());
IInstallableUnit[] ius = operationIUs;
String details = profileChangeOperation.getResolutionDetails();
{
setSystem(false);
setUser(false);
setPriority(LONG);
}
@Override
protected IStatus run(IProgressMonitor monitor) {
getCatalog().installErrorReport(monitor, r, items, ius, details);
return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS;
}
};
job.schedule();
}
}
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
IStatus status;
if (cause instanceof CoreException) {
status = ((CoreException) cause).getStatus();
} else {
status = new Status(IStatus.ERROR, MarketplaceClientUi.BUNDLE_ID, NLS.bind(
Messages.MarketplaceWizard_problemsPerformingProvisioningOperation,
new Object[] { cause.getMessage() }), cause);
}
MarketplaceClientUi.handle(status, StatusManager.SHOW | StatusManager.BLOCK | StatusManager.LOG);
} catch (InterruptedException e) {
// canceled
MarketplaceClientUi.log(IStatus.CANCEL, MarketplaceClientUi.BUNDLE_ID,
Messages.MarketplaceWizard_ProvisioningOperationCancelled, e);
} finally {
if (provisioningOperation != null) {
addedRepositoryLocations = provisioningOperation.getAddedRepositoryLocations();
}
}
}
//re-get the container - in case the wizard was closed in the meantime, this will be null...
wizardContainer = getContainer();
if (wizardContainer != null && wizardContainer.getCurrentPage() == featureSelectionWizardPage) {
featureSelectionWizardPage.updateMessage();
}
}
private void removeAddedRepositoryLocations() {
AbstractProvisioningOperation.removeRepositoryLocations(addedRepositoryLocations);
addedRepositoryLocations = null;
}
private Set<CatalogItem> computeNewInstallCatalogItems() {
Set<CatalogItem> items = new HashSet<CatalogItem>();
Map<CatalogItem, Collection<String>> iusByCatalogItem = new HashMap<CatalogItem, Collection<String>>();
for (CatalogItemEntry entry : getSelectionModel().getCatalogItemEntries()) {
List<FeatureEntry> features = entry.getChildren();
Collection<String> featureIds = new ArrayList<String>(features.size());
for (FeatureEntry feature : features) {
if (feature.computeChangeOperation() == Operation.INSTALL) {
featureIds.add(feature.getFeatureDescriptor().getId());
}
}
if (!featureIds.isEmpty()) {
iusByCatalogItem.put(entry.getItem(), featureIds);
}
}
for (IInstallableUnit unit : operationIUs) {
for (Entry<CatalogItem, Collection<String>> entry : iusByCatalogItem.entrySet()) {
if (entry.getValue().contains(unit.getId())) {
items.add(entry.getKey());
}
}
}
return items;
}
void initializeCatalog() {
final MarketplaceCatalog catalog = getCatalog();
synchronized (catalog) {
List<AbstractDiscoveryStrategy> discoveryStrategies = catalog.getDiscoveryStrategies();
for (AbstractDiscoveryStrategy strategy : discoveryStrategies) {
strategy.dispose();
}
discoveryStrategies.clear();
if (getConfiguration().getCatalogDescriptor() != null) {
MarketplaceDiscoveryStrategy discoveryStrategy = new MarketplaceDiscoveryStrategy(
getConfiguration().getCatalogDescriptor());
discoveryStrategy.setShellProvider(this);
discoveryStrategies.add(discoveryStrategy);
}
}
}
protected void updateNews() {
CatalogDescriptor catalogDescriptor = getConfiguration().getCatalogDescriptor();
INews news = null;
if (Boolean.parseBoolean(Platform.getDebugOption(DEBUG_NEWS_FLAG))) {
// use debug override values
String debugNewsUrl = Platform.getDebugOption(DEBUG_NEWS_URL);
if (debugNewsUrl != null && debugNewsUrl.length() > 0) {
News debugNews = new News();
news = debugNews;
debugNews.setUrl(debugNewsUrl);
String debugNewsTitle = Platform.getDebugOption(DEBUG_NEWS_TITLE);
if (debugNewsTitle == null || debugNewsTitle.length() == 0) {
debugNews.setShortTitle("Debug News"); //$NON-NLS-1$
} else {
debugNews.setShortTitle(debugNewsTitle);
}
debugNews.setTimestamp(System.currentTimeMillis());
}
}
if (news == null) {
// try requesting news from marketplace
try {
final INews[] result = new INews[1];
getContainer().run(true, true, new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
IStatus status = getCatalog().performNewsDiscovery(monitor);
if (!status.isOK() && status.getSeverity() != IStatus.CANCEL) {
// don't bother user with missing news
MarketplaceClientUi.handle(status, StatusManager.LOG);
}
result[0] = getCatalog().getNews();
}
});
if (result[0] != null) {
news = result[0];
}
} catch (InvocationTargetException e) {
final IStatus status = MarketplaceClientCore.computeStatus(e, Messages.MarketplaceViewer_unexpectedException);
MarketplaceClientUi.handle(status, StatusManager.LOG);
} catch (InterruptedException e) {
// cancelled by user
}
}
if (news == null) {
// use news from catalog
news = CatalogRegistry.getInstance().getCatalogNews(catalogDescriptor);
}
CatalogRegistry.getInstance().addCatalogNews(catalogDescriptor, news);
}
public Object suspendWizard() {
String catalogUrl = getCatalogUrl();
String key = appendWizardState(catalogUrl);
getContainer().getShell().close();
return key;
}
public void setInitialState(WizardState initialState) {
this.initialState = initialState;
}
public WizardState getInitialState() {
return initialState;
}
public static void resumeWizard(Display display, Object state, boolean proceedWithInstall) {
String catalogUrl = (String) state;
if (proceedWithInstall) {
org.eclipse.epp.mpc.ui.MarketplaceUrlHandler.SolutionInstallationInfo installInfo = MarketplaceUrlHandler.createSolutionInstallInfo(catalogUrl);
if (installInfo != null) {
MarketplaceUrlHandler.triggerInstall(installInfo);
return;
}
}
CatalogDescriptor descriptor = catalogUrl == null ? null : CatalogRegistry.getInstance().findCatalogDescriptor(
catalogUrl);
final MarketplaceWizardCommand command = new MarketplaceWizardCommand();
if (descriptor != null) {
descriptor = new CatalogDescriptor(descriptor);
descriptor.setLabel(MarketplaceUrlHandler.DESCRIPTOR_HINT);
command.setSelectedCatalogDescriptor(descriptor);
}
String mpcState = MarketplaceUrlHandler.getMPCState(catalogUrl);
if (mpcState != null && mpcState.length() > 0) {
try {
command.setWizardState(URLDecoder.decode(mpcState, "UTF-8")); //$NON-NLS-1$
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException(e); // should never happen
}
if (!proceedWithInstall) {
WizardState wizardState = new WizardState();
wizardState.setProceedWithInstallation(false);
command.setWizardDialogState(wizardState);
}
}
display.asyncExec(new Runnable() {
public void run() {
try {
command.execute(new ExecutionEvent());
} catch (ExecutionException e) {
IStatus status = MarketplaceClientCore.computeStatus(e, Messages.MarketplaceBrowserIntegration_cannotOpenMarketplaceWizard);
MarketplaceClientUi.handle(status,
StatusManager.SHOW | StatusManager.BLOCK | StatusManager.LOG);
}
}
});
}
}