blob: bffeab7a584f7466a50393d1ea567fb275519ad1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2008 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.update.internal.ui.wizards;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
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.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.DialogPage;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PropertyDialogAction;
import org.eclipse.ui.forms.HyperlinkSettings;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.ScrolledFormText;
import org.eclipse.update.core.ICategory;
import org.eclipse.update.core.IFeature;
import org.eclipse.update.core.IFeatureReference;
import org.eclipse.update.core.IImport;
import org.eclipse.update.core.IIncludedFeatureReference;
import org.eclipse.update.core.IPluginEntry;
import org.eclipse.update.core.ISiteFeatureReference;
import org.eclipse.update.core.IURLEntry;
import org.eclipse.update.core.Utilities;
import org.eclipse.update.core.VersionedIdentifier;
import org.eclipse.update.internal.core.ExtendedSite;
import org.eclipse.update.internal.core.UpdateCore;
import org.eclipse.update.internal.core.UpdateManagerUtils;
import org.eclipse.update.internal.operations.FeatureStatus;
import org.eclipse.update.internal.operations.OperationValidator;
import org.eclipse.update.internal.operations.UpdateUtils;
import org.eclipse.update.internal.operations.OperationValidator.InternalImport;
import org.eclipse.update.internal.operations.OperationValidator.RequiredFeaturesResult;
import org.eclipse.update.internal.ui.UpdateUI;
import org.eclipse.update.internal.ui.UpdateUIImages;
import org.eclipse.update.internal.ui.UpdateUIMessages;
import org.eclipse.update.internal.ui.model.FeatureReferenceAdapter;
import org.eclipse.update.internal.ui.model.SimpleFeatureAdapter;
import org.eclipse.update.internal.ui.model.SiteBookmark;
import org.eclipse.update.internal.ui.model.SiteCategory;
import org.eclipse.update.internal.ui.parts.DefaultContentProvider;
import org.eclipse.update.internal.ui.parts.SWTUtil;
import org.eclipse.update.internal.ui.parts.SharedLabelProvider;
import org.eclipse.update.operations.IInstallFeatureOperation;
import org.eclipse.update.operations.IUpdateModelChangedListener;
import org.eclipse.update.operations.OperationsManager;
import org.eclipse.update.search.IUpdateSearchSite;
import org.eclipse.update.search.UpdateSearchRequest;
public class ReviewPage extends BannerPage {
private Label label;
private ArrayList jobs;
private Label counterLabel;
private IStatus validationStatus;
private Collection problematicFeatures = new HashSet();
// feature that was recently selected or null
private IFeature newlySelectedFeature;
//
private FeatureStatus lastDisplayedStatus;
private PropertyDialogAction propertiesAction;
private ScrolledFormText descLabel;
private Button statusButton;
private Button moreInfoButton;
private Button propertiesButton;
private Button selectRequiredFeaturesButton;
private Button filterCheck;
private Button filterOlderVersionCheck;
private ContainmentFilter filter = new ContainmentFilter();
private LatestVersionFilter olderVersionFilter = new LatestVersionFilter();
private UpdateSearchRequest searchRequest;
//private int LABEL_ORDER = 1;
//private int VERSION_ORDER = 1;
//private int PROVIDER_ORDER = 1;
private ContainerCheckedTreeViewer treeViewer;
private boolean initialized;
private boolean isUpdateSearch;
class TreeContentProvider extends DefaultContentProvider implements
ITreeContentProvider {
public Object[] getElements(Object parent) {
return getSites();
}
public Object[] getChildren(final Object parent) {
if (parent instanceof SiteBookmark) {
SiteBookmark bookmark = (SiteBookmark) parent;
bookmark.getSite(null); // triggers catalog creation
Object[] children = bookmark.getCatalog(true,null);
ArrayList nonEmptyCategories = new ArrayList(children.length);
for (int i=0; i<children.length; i++)
if (hasChildren(children[i]))
nonEmptyCategories.add(children[i]);
return nonEmptyCategories.toArray();
} else if (parent instanceof SiteCategory) {
SiteCategory category = (SiteCategory)parent;
//return category.getChildren();
Object[] children = category.getChildren();
ArrayList list = new ArrayList(children.length);
for (int i=0; i<children.length; i++) {
if (children[i] instanceof FeatureReferenceAdapter) {
try {
IInstallFeatureOperation job = findJob((FeatureReferenceAdapter)children[i]);
if (job != null)
list.add(job);
} catch (CoreException e) {
UpdateCore.log(e.getStatus());
}
}
}
return list.toArray();
}
return new Object[0];
}
public Object getParent(Object element) {
if (element instanceof SiteCategory)
return ((SiteCategory) element).getBookmark();
if (element instanceof IInstallFeatureOperation) {
IFeature f = ((IInstallFeatureOperation)element).getFeature();
ISiteFeatureReference fr = f.getSite().getFeatureReference(f);
ICategory[] categories = fr.getCategories();
// if (categories != null && categories.length > 0)
// return categories[0];
SiteBookmark[] sites = (SiteBookmark[])((ITreeContentProvider)treeViewer.getContentProvider()).getElements(null);
for (int i=0; i<sites.length; i++) {
try {
if (sites[i].getSite(false, null).getURL() != f.getSite().getSiteContentProvider().getURL()) {
// if the site has mirrors check if this is from the mirror that user selected
if (sites[i].getSite(false, null) instanceof ExtendedSite) {
ExtendedSite site = (ExtendedSite)sites[i].getSite(false, null);
IURLEntry siteMirror = site.getSelectedMirror();
if (siteMirror != null && siteMirror.getURL().toExternalForm().equals(f.getSite().getSiteContentProvider().getURL().toExternalForm())) {
// this is the site so proceed with the loop
} else {
continue;
}
} else {
continue;
}
}
} catch (CoreException ce) {
return null;
}
Object[] children = sites[i].getCatalog(true, null);
for (int j = 0; j<children.length; j++) {
if (!(children[j] instanceof SiteCategory))
continue;
for (int c=0; c < categories.length; c++)
if (categories[c].getName().equals(((SiteCategory)children[j]).getName()))
return children[j];
}
}
}
return null;
}
public boolean hasChildren(Object element) {
return (element instanceof SiteBookmark || (
element instanceof SiteCategory && getChildren(element).length > 0));
}
private SiteBookmark[] getSites() {
if (searchRequest == null)
return new SiteBookmark[0];
else if (searchRequest.getScope().getSearchSites() == null ||
searchRequest.getScope().getSearchSites().length == 0) {
// this is an update search, so see if there are any jobs first,
// and get their sites
if (jobs != null) {
ArrayList sitesList = new ArrayList(jobs.size());
for (int i = 0; i < jobs.size(); i++) {
IInstallFeatureOperation op = (IInstallFeatureOperation) jobs
.get(i);
// we need a label for the site, so try to get it from the old
// feature update url
String label = null;
IFeature[] existingFeatures = UpdateUtils
.getInstalledFeatures(op.getFeature(), true);
if (existingFeatures != null
&& existingFeatures.length > 0) {
IURLEntry entry = op.getFeature()
.getUpdateSiteEntry();
label = entry.getAnnotation();
}
if (label == null)
label = op.getFeature().getSite().getURL().toExternalForm();
SiteBookmark bookmark = new SiteBookmark(label,
op.getFeature().getSite().getURL(), false);
if (sitesList.contains(bookmark))
continue;
else
sitesList.add(bookmark);
}
if (!sitesList.isEmpty())
return (SiteBookmark[]) sitesList
.toArray(new SiteBookmark[sitesList.size()]);
}
return new SiteBookmark[0];
} else {
// search for features
IUpdateSearchSite[] sites = searchRequest.getScope().getSearchSites();
SiteBookmark[] siteBookmarks = new SiteBookmark[sites.length];
for (int i = 0; i < sites.length; i++)
siteBookmarks[i] = new SiteBookmark(sites[i].getLabel(),
sites[i].getURL(), false);
return siteBookmarks;
}
}
}
class TreeLabelProvider extends SharedLabelProvider {
public Image getImage(Object obj) {
if (obj instanceof SiteBookmark)
return UpdateUI.getDefault().getLabelProvider().get(
UpdateUIImages.DESC_SITE_OBJ);
if (obj instanceof SiteCategory)
return UpdateUI.getDefault().getLabelProvider().get(
UpdateUIImages.DESC_CATEGORY_OBJ);
if (obj instanceof IInstallFeatureOperation) {
IFeature feature = ((IInstallFeatureOperation) obj).getFeature();
boolean patch = feature.isPatch();
//boolean problematic=problematicFeatures.contains(feature) && treeViewer.getChecked(obj);
boolean featureIsProblematic = isFeatureProblematic(feature);
boolean problematic = treeViewer.getChecked(obj) && featureIsProblematic;
if (!problematic && featureIsProblematic) {
Object parent = ((TreeContentProvider)treeViewer.getContentProvider()).getParent(obj);
if(parent == null)
return super.getImage(obj);
problematic = treeViewer.getChecked(parent) && !treeViewer.getGrayed(parent);
}
if (patch) {
return get(UpdateUIImages.DESC_EFIX_OBJ, problematic? F_ERROR : 0);
} else {
return get(UpdateUIImages.DESC_FEATURE_OBJ, problematic? F_ERROR : 0);
}
}
return super.getImage(obj);
}
public String getText(Object obj) {
if (obj instanceof SiteBookmark)
return ((SiteBookmark) obj).getLabel();
/*
if (obj instanceof SiteCategory)
return obj.toString();
*/
if (obj instanceof IInstallFeatureOperation) {
IInstallFeatureOperation job = (IInstallFeatureOperation) obj;
IFeature feature = job.getFeature();
return feature.getLabel() + " " + feature //$NON-NLS-1$
.getVersionedIdentifier()
.getVersion()
.toString();
}
return super.getText(obj);
}
}
class ModelListener implements IUpdateModelChangedListener {
public void objectChanged(Object object, String property) {
treeViewer.refresh();
checkItems();
}
public void objectsAdded(Object parent, Object[] children) {
treeViewer.refresh();
checkItems();
}
public void objectsRemoved(Object parent, Object[] children) {
treeViewer.refresh();
checkItems();
}
private void checkItems() {
TreeItem[] items = treeViewer.getTree().getItems();
for (int i = 0; i < items.length; i++) {
SiteBookmark bookmark = (SiteBookmark) items[i].getData();
treeViewer.setChecked(bookmark, bookmark.isSelected());
String[] ignoredCats = bookmark.getIgnoredCategories();
treeViewer.setGrayed(bookmark, ignoredCats.length > 0
&& bookmark.isSelected());
}
}
}
class ContainmentFilter extends ViewerFilter {
private IInstallFeatureOperation[] selectedJobs;
public boolean select(Viewer viewer, Object parent, Object element) {
if (element instanceof IInstallFeatureOperation) {
return !isContained((IInstallFeatureOperation) element) || isSelected( selectedJobs, (IInstallFeatureOperation)element);
} else if ( (element instanceof SiteCategory) || (element instanceof SiteBookmark)){
Object[] children = ((ITreeContentProvider)((ContainerCheckedTreeViewer)viewer).getContentProvider()).getChildren(element);
for ( int i = 0; i < children.length; i++) {
if (select(viewer, element, children[i])) {
return true;
}
}
return false;
}
return true;
}
private boolean isContained(IInstallFeatureOperation job) {
VersionedIdentifier vid = job.getFeature().getVersionedIdentifier();
for (int i = 0; i < jobs.size(); i++) {
IInstallFeatureOperation candidate = (IInstallFeatureOperation) jobs.get(i);
if (candidate.equals(job))
continue;
IFeature feature = candidate.getFeature();
if (includes(feature, vid,null))
return true;
}
return false;
}
private boolean includes(IFeature feature, VersionedIdentifier vid, ArrayList cycleCandidates) {
try {
if (cycleCandidates == null)
cycleCandidates = new ArrayList();
if (cycleCandidates.contains(feature))
throw Utilities.newCoreException(NLS.bind(UpdateUIMessages.InstallWizard_ReviewPage_cycle, feature.getVersionedIdentifier().toString()), null);
else
cycleCandidates.add(feature);
IFeatureReference[] irefs =
feature.getIncludedFeatureReferences();
for (int i = 0; i < irefs.length; i++) {
IFeatureReference iref = irefs[i];
IFeature ifeature = UpdateUtils.getIncludedFeature(feature, iref);
VersionedIdentifier ivid =
ifeature.getVersionedIdentifier();
if (ivid.equals(vid))
return true;
if (includes(ifeature, vid, cycleCandidates))
return true;
}
return false;
} catch (CoreException e) {
return false;
} finally {
// after this feature has been DFS-ed, it is no longer a cycle candidate
cycleCandidates.remove(feature);
}
}
public IInstallFeatureOperation[] getSelectedJobs() {
return selectedJobs;
}
public void setSelectedJobs(IInstallFeatureOperation[] selectedJobs) {
this.selectedJobs = selectedJobs;
}
}
class LatestVersionFilter extends ViewerFilter {
private IInstallFeatureOperation[] selectedJobs;
public boolean select(Viewer viewer, Object parent, Object element) {
if (element instanceof IInstallFeatureOperation) {
return isLatestVersion((IInstallFeatureOperation) element) || isSelected( selectedJobs, (IInstallFeatureOperation)element);
} else if ( (element instanceof SiteCategory) || (element instanceof SiteBookmark)){
Object[] children = ((ITreeContentProvider)((ContainerCheckedTreeViewer)viewer).getContentProvider()).getChildren(element);
for ( int i = 0; i < children.length; i++) {
if (select(viewer, element, children[i])) {
return true;
}
}
return false;
}
return true;
}
private boolean isLatestVersion(IInstallFeatureOperation job) {
IFeature feature = job.getFeature();
for (int i = 0; i < jobs.size(); i++) {
IInstallFeatureOperation candidateJob = (IInstallFeatureOperation) jobs.get(i);
if (candidateJob.equals(job))
continue;
IFeature candidate = candidateJob.getFeature();
if (feature.getSite() != job.getFeature().getSite())
continue;
if (!feature.getVersionedIdentifier().getIdentifier().equals(candidate.getVersionedIdentifier().getIdentifier()))
continue;
if (!feature.getVersionedIdentifier().getVersion().isGreaterOrEqualTo(candidate.getVersionedIdentifier().getVersion()))
return false;
}
return true;
}
public IInstallFeatureOperation[] getSelectedJobs() {
return selectedJobs;
}
public void setSelectedJobs(IInstallFeatureOperation[] selectedJobs) {
this.selectedJobs = selectedJobs;
}
}
class FeaturePropertyDialogAction extends PropertyDialogAction {
private IStructuredSelection selection;
public FeaturePropertyDialogAction(
Shell shell,
ISelectionProvider provider) {
super(shell, provider);
}
public IStructuredSelection getStructuredSelection() {
return selection;
}
public void selectionChanged(IStructuredSelection selection) {
this.selection = selection;
}
}
/**
* Constructor for ReviewPage2
*/
public ReviewPage(boolean isUpdateSearch, UpdateSearchRequest searchRequest, ArrayList jobs) {
super("Review"); //$NON-NLS-1$
this.isUpdateSearch = isUpdateSearch;
this.jobs = jobs;
if (this.jobs==null) this.jobs = new ArrayList();
this.searchRequest = searchRequest;
setTitle(UpdateUIMessages.InstallWizard_ReviewPage_title);
setDescription(UpdateUIMessages.InstallWizard_ReviewPage_desc);
UpdateUI.getDefault().getLabelProvider().connect(this);
setBannerVisible(false);
}
public void dispose() {
UpdateUI.getDefault().getLabelProvider().disconnect(this);
super.dispose();
}
public void setVisible(boolean visible) {
super.setVisible(visible);
// when searching for updates, only nested patches can be shown.
// when searching for features, features and patches can be shown
String filterText = filterCheck.getText();
String filterFeatures = UpdateUIMessages.InstallWizard_ReviewPage_filterFeatures;
String filterPatches = UpdateUIMessages.InstallWizard_ReviewPage_filterPatches;
if (isUpdateSearch && filterText.equals(filterFeatures))
filterCheck.setText(filterPatches);
else if ( !isUpdateSearch && filterText.equals(filterPatches))
filterCheck.setText(filterFeatures);
if (visible && !initialized) {
initialized = true;
// jobs.clear();
// setDescription(UpdateUI.getString("InstallWizard.ReviewPage.searching")); //$NON-NLS-1$;
// label.setText(UpdateUI.getString("")); //$NON-NLS-1$
getShell().getDisplay().asyncExec(new Runnable() {
public void run() {
// searchRunner.runSearch();
performPostSearchProcessing();
}
});
}
}
private void performPostSearchProcessing() {
BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
public void run() {
if (treeViewer != null) {
// treeViewer.refresh();
// treeViewer.getTree().layout(true);
if (isUpdateSearch) {
selectTrueUpdates();
}
}
pageChanged();
int totalCount = jobs != null ? jobs.size(): 0;
if(totalCount >0) {
setDescription(UpdateUIMessages.InstallWizard_ReviewPage_desc);
label.setText(UpdateUIMessages.InstallWizard_ReviewPage_label);
} else {
if (isUpdateSearch)
setDescription(UpdateUIMessages.InstallWizard_ReviewPage_zeroUpdates);
else
setDescription(UpdateUIMessages.InstallWizard_ReviewPage_zeroFeatures);
label.setText(""); //$NON-NLS-1$
}
}
});
}
private void selectTrueUpdates() {
ArrayList trueUpdates = new ArrayList();
for (int i=0; i<jobs.size(); i++) {
IInstallFeatureOperation job = (IInstallFeatureOperation)jobs.get(i);
if (!UpdateUtils.isPatch(job.getFeature()))
trueUpdates.add(job);
}
treeViewer.setCheckedElements(trueUpdates.toArray());
validateSelection(new NullProgressMonitor());
}
/**
* @see DialogPage#createControl(Composite)
*/
public Control createContents(Composite parent) {
Composite client = new Composite(parent, SWT.NULL);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
layout.marginWidth = layout.marginHeight = 0;
client.setLayout(layout);
label = new Label(client, SWT.NULL);
label.setText(UpdateUIMessages.InstallWizard_ReviewPage_label);
GridData gd = new GridData();
gd.horizontalSpan = 2;
label.setLayoutData(gd);
createTreeViewer(client);
Composite comp = new Composite(client, SWT.NONE);
layout = new GridLayout();
layout.marginWidth = layout.marginHeight = 0;
comp.setLayout(layout);
comp.setLayoutData(new GridData(GridData.FILL_VERTICAL));
Composite buttonContainer = new Composite(comp, SWT.NULL);
gd = new GridData(GridData.FILL_VERTICAL);
buttonContainer.setLayoutData(gd);
layout = new GridLayout();
layout.marginWidth = 0;
layout.marginHeight = 0; //30?
buttonContainer.setLayout(layout);
buttonContainer.setLayoutData(new GridData(GridData.FILL_BOTH));
Button button = new Button(buttonContainer, SWT.PUSH);
button.setText(UpdateUIMessages.InstallWizard_ReviewPage_deselectAll);
gd =
new GridData(
GridData.HORIZONTAL_ALIGN_FILL
| GridData.VERTICAL_ALIGN_BEGINNING);
button.setLayoutData(gd);
SWTUtil.setButtonDimensionHint(button);
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
handleDeselectAll();
}
});
moreInfoButton = new Button(buttonContainer, SWT.PUSH);
moreInfoButton.setText(UpdateUIMessages.InstallWizard_ReviewPage_moreInfo);
gd =
new GridData(
GridData.HORIZONTAL_ALIGN_FILL
| GridData.VERTICAL_ALIGN_BEGINNING);
moreInfoButton.setLayoutData(gd);
SWTUtil.setButtonDimensionHint(moreInfoButton);
moreInfoButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
handleMoreInfo();
}
});
moreInfoButton.setEnabled(false);
propertiesButton = new Button(buttonContainer, SWT.PUSH);
propertiesButton.setText(UpdateUIMessages.InstallWizard_ReviewPage_properties);
gd =
new GridData(
GridData.HORIZONTAL_ALIGN_FILL
| GridData.VERTICAL_ALIGN_BEGINNING);
propertiesButton.setLayoutData(gd);
SWTUtil.setButtonDimensionHint(propertiesButton);
propertiesButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
handleProperties();
}
});
propertiesButton.setEnabled(false);
selectRequiredFeaturesButton = new Button(buttonContainer, SWT.PUSH);
selectRequiredFeaturesButton.setText(UpdateUIMessages.InstallWizard_ReviewPage_selectRequired);
gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL
| GridData.VERTICAL_ALIGN_BEGINNING);
selectRequiredFeaturesButton.setLayoutData(gd);
SWTUtil.setButtonDimensionHint(selectRequiredFeaturesButton);
selectRequiredFeaturesButton
.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
BusyIndicator.showWhile(e.display, new Runnable() {
public void run() {
Object[] elements = treeViewer.getExpandedElements();
treeViewer.expandAll();
treeViewer.setExpandedElements(elements);
selectRequiredFeatures();
updateItemCount();
}
});
}
});
statusButton = new Button(buttonContainer, SWT.PUSH);
statusButton.setText(UpdateUIMessages.InstallWizard_ReviewPage_showStatus);
gd =
new GridData(
GridData.HORIZONTAL_ALIGN_FILL
| GridData.VERTICAL_ALIGN_BEGINNING);
statusButton.setLayoutData(gd);
SWTUtil.setButtonDimensionHint(statusButton);
statusButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
showStatus();
}
});
//new Label(client, SWT.NULL);
counterLabel = new Label(client, SWT.NULL);
gd = new GridData();
gd.horizontalSpan = 2;
counterLabel.setLayoutData(gd);
filterOlderVersionCheck = new Button(client, SWT.CHECK);
filterOlderVersionCheck.setText(UpdateUIMessages.InstallWizard_ReviewPage_filterOlderFeatures);
filterOlderVersionCheck.setSelection(true);
treeViewer.addFilter(olderVersionFilter);
filterOlderVersionCheck.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
IInstallFeatureOperation[] jobs = getSelectedJobs();
if (filterOlderVersionCheck.getSelection())
treeViewer.addFilter(olderVersionFilter);
else
treeViewer.removeFilter(olderVersionFilter);
olderVersionFilter.setSelectedJobs(jobs);
pageChanged(jobs);
}
});
gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.horizontalSpan = 2;
filterOlderVersionCheck.setLayoutData(gd);
filterCheck = new Button(client, SWT.CHECK);
filterCheck.setText(UpdateUIMessages.InstallWizard_ReviewPage_filterFeatures);
filterCheck.setSelection(false);
//tableViewer.addFilter(filter);
filterCheck.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
IInstallFeatureOperation[] jobs = getSelectedJobs();
if (filterCheck.getSelection()) {
// make sure model is local
if (downloadIncludedFeatures()) {
treeViewer.addFilter(filter);
} else {
filterCheck.setSelection(false);
}
} else {
treeViewer.removeFilter(filter);
}
filter.setSelectedJobs(jobs);
pageChanged(jobs);
}
});
gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.horizontalSpan = 2;
filterCheck.setLayoutData(gd);
pageChanged();
PlatformUI.getWorkbench().getHelpSystem().setHelp(client, "org.eclipse.update.ui.MultiReviewPage2"); //$NON-NLS-1$
Dialog.applyDialogFont(parent);
return client;
}
private void createTreeViewer(final Composite parent) {
SashForm sform = new SashForm(parent, SWT.VERTICAL);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.widthHint = 250;
gd.heightHint =100;
sform.setLayoutData(gd);
treeViewer = new ContainerCheckedTreeViewer(sform, SWT.H_SCROLL | SWT.V_SCROLL
| SWT.BORDER);
treeViewer.getTree().setLayoutData(new GridData(GridData.FILL_BOTH));
treeViewer.setContentProvider(new TreeContentProvider());
treeViewer.setLabelProvider(new TreeLabelProvider());
treeViewer.setInput(UpdateUI.getDefault().getUpdateModel());
treeViewer
.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent e) {
handleSelectionChanged((IStructuredSelection) e.getSelection());
}
});
treeViewer.addCheckStateListener(new ICheckStateListener() {
public void checkStateChanged(CheckStateChangedEvent event) {
/*
* validateSelection(); Object site =
* getSite(event.getElement()); ArrayList descendants = new
* ArrayList(); collectDescendants(site, descendants); Object[]
* nodes = new Object[descendants.size()]; for (int i = 0; i <
* nodes.length; i++) nodes[i] = descendants.get(i);
* treeViewer.update(nodes, null); updateItemCount();
*/
try {
getContainer().run(true, true,
getCheckStateOperation(event, parent.getDisplay()));
getContainer().updateButtons();
updateStatusButton();
} catch (InvocationTargetException e) {
UpdateUI.logException(e);
} catch (InterruptedException e) {
UpdateUI.logException(e);
}
}
});
descLabel = new ScrolledFormText(sform, true);
descLabel.setText(""); //$NON-NLS-1$
descLabel.setBackground(parent.getBackground());
HyperlinkSettings settings = new HyperlinkSettings(parent.getDisplay());
descLabel.getFormText().setHyperlinkSettings(settings);
descLabel.getFormText().addHyperlinkListener(new HyperlinkAdapter() {
public void linkActivated(HyperlinkEvent e) {
Object href = e.getHref();
if (href==null)
return;
try {
URL url = new URL(href.toString());
PlatformUI.getWorkbench().getBrowserSupport().getExternalBrowser().openURL(url);
}
catch (PartInitException ex) {
UpdateUI.logException(ex);
}
catch (MalformedURLException ex) {
UpdateUI.logException(ex);
}
}
});
gd = new GridData(SWT.FILL, SWT.FILL, true, true);
gd.horizontalSpan = 1;
descLabel.setLayoutData(gd);
sform.setWeights(new int[] {10, 2});
}
private IRunnableWithProgress getCheckStateOperation(
final CheckStateChangedEvent event, final Display display) {
return new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) {
monitor.beginTask(UpdateUIMessages.ReviewPage_validating,
IProgressMonitor.UNKNOWN);
validateSelection(monitor);
if (monitor.isCanceled()) {
undoStateChange(event);
monitor.done();
return;
}
Object site = getSite(event.getElement());
ArrayList descendants = new ArrayList();
collectDescendants(site, descendants, monitor);
final Object[] nodes = new Object[descendants.size()];
if (monitor.isCanceled()) {
undoStateChange(event);
monitor.done();
return;
}
for (int i = 0; i < nodes.length; i++)
nodes[i] = descendants.get(i);
display.syncExec(new Runnable() {
public void run() {
treeViewer.update(nodes, null);
updateItemCount();
}
});
monitor.done();
}
};
}
private void undoStateChange(final CheckStateChangedEvent e) {
treeViewer.getControl().getDisplay().syncExec(new Runnable() {
public void run() {
treeViewer.setChecked(e.getElement(), !e.getChecked());
}
});
}
private void handleSelectionChanged(IStructuredSelection ssel) {
Object item = ssel.getFirstElement();
String description = null;
if (item instanceof SiteBookmark) {
description = ((SiteBookmark)item).getDescription();
} else if (item instanceof SiteCategory) {
IURLEntry descEntry = ((SiteCategory)item).getCategory().getDescription();
if (descEntry != null)
description = descEntry.getAnnotation();
} else if (item instanceof IInstallFeatureOperation) {
jobSelected(ssel);
return;
}
if (description == null)
description = ""; //$NON-NLS-1$
//descLabel.setText(UpdateManagerUtils.getWritableXMLString(description), false, true);
updateDescription(description);
propertiesButton.setEnabled(false);
moreInfoButton.setEnabled(false);
}
/*
private void fillContextMenu(IMenuManager manager) {
if (treeViewer.getSelection().isEmpty()) return;
Action action = new Action(UpdateUIMessages.InstallWizard_ReviewPage_prop) {
public void run() {
handleProperties();
}
};
manager.add(action);
}
*/
private void jobSelected(IStructuredSelection selection) {
IInstallFeatureOperation job = (IInstallFeatureOperation) selection.getFirstElement();
IFeature feature = job != null ? job.getFeature() : null;
IURLEntry descEntry = feature != null ? feature.getDescription() : null;
String desc = null;
if (descEntry != null)
desc = descEntry.getAnnotation();
if (desc == null)
desc = ""; //$NON-NLS-1$
//descLabel.setText(UpdateManagerUtils.getWritableXMLString(desc));
updateDescription(desc);
propertiesButton.setEnabled(feature != null);
moreInfoButton.setEnabled(job != null && getMoreInfoURL(job) != null);
}
private void updateDescription(String text) {
descLabel.getFormText().setText(UpdateManagerUtils.getWritableXMLString(text), false, true);
descLabel.reflow(true);
}
private void pageChanged() {
pageChanged(this.getSelectedJobs());
}
private void pageChanged( IInstallFeatureOperation[] jobsSelected) {
if (jobsSelected.length == 0) {
lastDisplayedStatus = null;
setErrorMessage(null);
setPageComplete(false);
setValidationStatus(null);
problematicFeatures.clear();
}
treeViewer.setCheckedElements(jobsSelected);
//validateSelection();
treeViewer.refresh();
treeViewer.setCheckedElements(jobsSelected);
updateItemCount();
}
private void setValidationStatus(IStatus newValidationStatus) {
this.validationStatus = newValidationStatus;
updateStatusButton();
}
private void updateStatusButton() {
statusButton.getDisplay().syncExec(new Runnable() {
public void run() {
boolean newState = validationStatus != null && validationStatus.getSeverity() != IStatus.OK;
statusButton.setEnabled(newState);
}
});
}
private void updateItemCount() {
updateItemCount(-1, -1);
}
private int getSelectedJobsUniqueCount() {
Object[] checkedElements = getSelectedJobs();
Set set = new HashSet();
for (int i=0; i<checkedElements.length; i++) {
IInstallFeatureOperation job = (IInstallFeatureOperation)checkedElements[i];
IFeature feature = job.getFeature();
if (set.contains(feature))
continue;
set.add(feature);
}
return set.size();
}
private void updateItemCount(int checkedCount, int totalCount) {
if (checkedCount == -1) {
checkedCount = getSelectedJobsUniqueCount();
}
if (totalCount == -1) {
totalCount = jobs.size();
}
String total = "" + totalCount; //$NON-NLS-1$
String selected = "" + checkedCount; //$NON-NLS-1$
counterLabel.setText(
NLS.bind(UpdateUIMessages.InstallWizard_ReviewPage_counter, (new String[] { selected, total })));
counterLabel.getParent().layout();
}
// private void handleSelectAll(boolean select) {
// treeViewer.setAllChecked(select);
//// make sure model is local (download using progress monitor from container)
// downloadIncludedFeatures();
//
// treeViewer.getControl().getDisplay().asyncExec(new Runnable() {
// public void run() {
// pageChanged();
// }
// });
// }
// private void handleSelectAll(boolean select) {
// treeViewer.setAllChecked(select);
//// make sure model is local (download using progress monitor from container)
// downloadIncludedFeatures();
//
// treeViewer.getControl().getDisplay().asyncExec(new Runnable() {
// public void run() {
// pageChanged();
// }
// });
//}
private void handleDeselectAll() {
//treeViewer.setCheckedElements(new Object[0]);
IInstallFeatureOperation[] selectedJobs = getSelectedJobs();
for( int i = 0; i < selectedJobs.length; i++)
treeViewer.setChecked( selectedJobs[i], false);
// make sure model is local (download using progress monitor from
// container)
// downloadIncludedFeatures();
treeViewer.getControl().getDisplay().asyncExec(new Runnable() {
public void run() {
pageChanged();
}
});
}
private void handleProperties() {
final IStructuredSelection selection =
(IStructuredSelection) treeViewer.getSelection();
final IInstallFeatureOperation job =
(IInstallFeatureOperation) selection.getFirstElement();
if (propertiesAction == null) {
propertiesAction =
new FeaturePropertyDialogAction(getShell(), treeViewer);
}
BusyIndicator
.showWhile(treeViewer.getControl().getDisplay(), new Runnable() {
public void run() {
SimpleFeatureAdapter adapter =
new SimpleFeatureAdapter(job.getFeature());
propertiesAction.selectionChanged(
new StructuredSelection(adapter));
propertiesAction.run();
}
});
}
private String getMoreInfoURL(IInstallFeatureOperation job) {
IURLEntry desc = job.getFeature().getDescription();
if (desc != null) {
URL url = desc.getURL();
return (url == null) ? null : url.toString();
}
return null;
}
private void handleMoreInfo() {
IStructuredSelection selection =
(IStructuredSelection) treeViewer.getSelection();
final IInstallFeatureOperation selectedJob =
(IInstallFeatureOperation) selection.getFirstElement();
BusyIndicator
.showWhile(treeViewer.getControl().getDisplay(), new Runnable() {
public void run() {
String urlName = getMoreInfoURL(selectedJob);
UpdateUI.showURL(urlName);
}
});
}
private IStatus selectRequiredFeatures() {
IInstallFeatureOperation[] jobs = getSelectedJobs();
RequiredFeaturesResult requiredFeaturesResult = ((OperationValidator)OperationsManager
.getValidator()).getRequiredFeatures(jobs);
setValidationStatus(requiredFeaturesResult.getStatus());
Set requiredFeatures = requiredFeaturesResult.getRequiredFeatures();
problematicFeatures.clear();
Iterator requiredFeaturesIterator = requiredFeatures.iterator();
ArrayList toBeInstalled = new ArrayList();
while (requiredFeaturesIterator.hasNext()) {
IImport requiredFeature = ((InternalImport)requiredFeaturesIterator.next()).getImport();
IInstallFeatureOperation currentFeatureSelected = null;
TreeItem[] items = treeViewer.getTree().getItems();
for (int i = 0; i < items.length; i++) {
TreeItem[] siteRootContent = items[i].getItems();
for (int j = 0; j < siteRootContent.length; j++) {
if (siteRootContent[j].getData() instanceof SiteCategory) {
if ( !treeViewer.getChecked(siteRootContent[j].getData())) {
// this category has not been checked at all so we have to create its features
treeViewer.createChildren(siteRootContent[j]);
}
TreeItem[] features = siteRootContent[j].getItems();
if ((features.length > 0) && (features[0].getData() == null)) {
// this category has been checked but not visited yet so restore the features in it
treeViewer.createChildren(siteRootContent[j]);
treeViewer.updateChildrenItems(siteRootContent[j]);
features = siteRootContent[j].getItems();
}
for (int k = 0; k < features.length; k++) {
currentFeatureSelected = decideOnFeatureSelection(
requiredFeature,
(IInstallFeatureOperation) features[k]
.getData(), currentFeatureSelected);
}
} else if (siteRootContent[j].getData() instanceof IInstallFeatureOperation) {
currentFeatureSelected = decideOnFeatureSelection(
requiredFeature,
(IInstallFeatureOperation) siteRootContent[j]
.getData(), currentFeatureSelected);
}
}
}
if (currentFeatureSelected != null)
toBeInstalled.add(currentFeatureSelected);
}
if (!toBeInstalled.isEmpty()) {
Iterator toBeInstalledIterator = toBeInstalled.iterator();
while (toBeInstalledIterator.hasNext()) {
IInstallFeatureOperation current = (IInstallFeatureOperation)toBeInstalledIterator.next();
treeViewer.setChecked(current, true);
}
return selectRequiredFeatures();
} else {
problematicFeatures.clear();
if (validationStatus != null) {
IStatus[] status = validationStatus.getChildren();
for (int i = 0; i < status.length; i++) {
IStatus singleStatus = status[i];
if (isSpecificStatus(singleStatus)) {
IFeature f = ((FeatureStatus) singleStatus)
.getFeature();
problematicFeatures.add(f);
}
}
}
setPageComplete(validationStatus == null
|| validationStatus.getSeverity() == IStatus.WARNING);
lastDisplayedStatus = null;
updateWizardMessage();
treeViewer.update(getSelectedJobs(), null);
return validationStatus;
}
}
public IInstallFeatureOperation[] getSelectedJobs() {
Object[] selected = treeViewer.getCheckedElements();
ArrayList selectedJobs = new ArrayList(selected.length);
for (int i=0; i<selected.length; i++)
if (selected[i] instanceof IInstallFeatureOperation)
selectedJobs.add(selected[i]);
return (IInstallFeatureOperation[])selectedJobs.toArray(new IInstallFeatureOperation[selectedJobs.size()]);
}
public void validateSelection(IProgressMonitor monitor) {
IInstallFeatureOperation[] jobs;
final IInstallFeatureOperation[][] bag = new IInstallFeatureOperation[1][];
treeViewer.getControl().getDisplay().syncExec(new Runnable() {
public void run() {
bag[0] = getSelectedJobs();
}
});
if (monitor.isCanceled()) return;
jobs = bag[0];
setValidationStatus(OperationsManager.getValidator()
.validatePendingChanges(jobs));
problematicFeatures.clear();
if (monitor.isCanceled()) return;
if (validationStatus != null) {
IStatus[] status = validationStatus.getChildren();
for (int i = 0; i < status.length; i++) {
IStatus singleStatus = status[i];
if (isSpecificStatus(singleStatus)) {
IFeature f = ((FeatureStatus) singleStatus).getFeature();
problematicFeatures.add(f);
}
}
}
if (monitor.isCanceled())
return;
treeViewer.getControl().getDisplay().syncExec(new Runnable() {
public void run() {
setPageComplete(validationStatus == null
|| validationStatus.getSeverity() == IStatus.WARNING);
/*
statusButton.setEnabled(validationStatus != null
&& validationStatus.getSeverity() != IStatus.OK);
*/
updateWizardMessage();
}
});
}
private void showStatus() {
if (validationStatus != null) {
new StatusDialog().open();
}
}
/**
* Check whether status is relevant to show for
* a specific feature or is a other problem
* @param status
* @return true if status is FeatureStatus with
* specified feature and certain error codes
*/
private boolean isSpecificStatus(IStatus status){
if(!(status instanceof FeatureStatus)){
return false;
}
if(status.getSeverity()!=IStatus.ERROR){
return false;
}
FeatureStatus featureStatus = (FeatureStatus) status;
if(featureStatus.getFeature()==null){
return false;
}
return 0!= (featureStatus.getCode()
& FeatureStatus.CODE_CYCLE
+ FeatureStatus.CODE_ENVIRONMENT
+ FeatureStatus.CODE_EXCLUSIVE
+ FeatureStatus.CODE_OPTIONAL_CHILD
+ FeatureStatus.CODE_PREREQ_FEATURE
+ FeatureStatus.CODE_PREREQ_PLUGIN);
}
/**
* Update status in the wizard status area
*/
private void updateWizardMessage() {
if (validationStatus == null) {
lastDisplayedStatus=null;
setErrorMessage(null);
} else if (validationStatus.getSeverity() == IStatus.WARNING) {
lastDisplayedStatus=null;
setErrorMessage(null);
setMessage(validationStatus.getMessage(), IMessageProvider.WARNING);
} else {
// 1. Feature selected, creating a problem for it, show status for it
if(newlySelectedFeature !=null){
IStatus[] status = validationStatus.getChildren();
for(int s =0; s< status.length; s++){
if(isSpecificStatus(status[s])){
FeatureStatus featureStatus = (FeatureStatus)status[s];
if(newlySelectedFeature.equals(featureStatus.getFeature())){
lastDisplayedStatus=featureStatus;
setErrorMessage(featureStatus.getMessage());
return;
}
}
}
}
// 2. show old status if possible (it is still valid)
if(lastDisplayedStatus !=null){
IStatus[] status = validationStatus.getChildren();
for(int i=0; i<status.length; i++){
if(lastDisplayedStatus.equals(status[i])){
//lastDisplayedStatus=lastDisplayedStatus;
//setErrorMessage(status[i].getMessage());
return;
}
}
lastDisplayedStatus = null;
}
// 3. pick the first problem that is specific to some feature
IStatus[] status = validationStatus.getChildren();
for(int s =0; s< status.length; s++){
if(isSpecificStatus(status[s])){
lastDisplayedStatus = (FeatureStatus)status[s];
setErrorMessage(status[s].getMessage());
return;
}
}
// 4. display the first problem (no problems specify a feature)
if(status.length>0){
IStatus singleStatus=status[0];
setErrorMessage(singleStatus.getMessage());
}else{
// 5. not multi or empty multi status
setErrorMessage(UpdateUIMessages.InstallWizard_ReviewPage_invalid_long);
}
}
}
class StatusDialog extends ErrorDialog {
// Button detailsButton;
public StatusDialog() {
super(getContainer().getShell(), UpdateUIMessages.InstallWizard_ReviewPage_invalid_short, null,
validationStatus, IStatus.OK | IStatus.INFO
| IStatus.WARNING | IStatus.ERROR);
}
// protected Button createButton(
// Composite parent,
// int id,
// String label,
// boolean defaultButton) {
// Button b = super.createButton(parent, id, label, defaultButton);
// if(IDialogConstants.DETAILS_ID == id){
// detailsButton = b;
// }
// return b;
// }
public void create() {
super.create();
buttonPressed(IDialogConstants.DETAILS_ID);
// if(detailsButton!=null){
// detailsButton.dispose();
// }
}
}
/**
* @return true, if completed, false if canceled by the user
*/
private boolean downloadIncludedFeatures() {
try {
Downloader downloader = new Downloader(jobs);
getContainer().run(true, true, downloader);
return !downloader.isCanceled();
} catch (InvocationTargetException ite) {
} catch (InterruptedException ie) {
}
return true;
}
/**
* Runnable to resolve included feature references.
*/
class Downloader implements IRunnableWithProgress {
boolean canceled = false;
/**
* List of IInstallFeatureOperation
*/
ArrayList operations;
public Downloader(ArrayList installOperations) {
operations = installOperations;
}
public boolean isCanceled() {
return canceled;
}
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
for (int i = 0; i < operations.size(); i++) {
IInstallFeatureOperation candidate = (IInstallFeatureOperation) operations
.get(i);
IFeature feature = candidate.getFeature();
try {
IFeatureReference[] irefs = feature
.getRawIncludedFeatureReferences();
for (int f = 0; f < irefs.length; f++) {
if (monitor.isCanceled()) {
canceled = true;
return;
}
IFeatureReference iref = irefs[f];
iref.getFeature(monitor);
}
} catch (CoreException e) {
}
}
if (monitor.isCanceled()) {
canceled = true;
}
}
}
private IInstallFeatureOperation findJob(FeatureReferenceAdapter feature)
throws CoreException {
if (jobs == null)
return null;
for (int i = 0; i < jobs.size(); i++)
if (((IInstallFeatureOperation) jobs.get(i)).getFeature()
.getVersionedIdentifier().equals(feature.getFeatureReference()
.getVersionedIdentifier()))
return (IInstallFeatureOperation) jobs.get(i);
return null;
}
private Object getSite(Object object) {
ITreeContentProvider provider = (ITreeContentProvider)treeViewer.getContentProvider();
while (object != null && !(object instanceof SiteBookmark)) {
object = provider.getParent(object);
}
return object;
}
private void collectDescendants(Object root, ArrayList list,
IProgressMonitor monitor) {
ITreeContentProvider provider = (ITreeContentProvider) treeViewer
.getContentProvider();
Object[] children = provider.getChildren(root);
if (children != null && children.length > 0)
for (int i = 0; i < children.length; i++) {
if (monitor.isCanceled())
return;
list.add(children[i]);
collectDescendants(children[i], list, monitor);
}
}
public boolean isFeatureGood(IImport requiredFeature, IFeature feature) {
return isFeatureGood(requiredFeature, feature, new ArrayList());
}
public boolean isFeatureGood(IImport prereq, IFeature feature, List visitedFeatures) {
if (prereq.getKind() == IImport.KIND_FEATURE) {
if ((!prereq.getVersionedIdentifier().getIdentifier().equals(
feature.getVersionedIdentifier().getIdentifier()))) {
IIncludedFeatureReference[] iifr = null;
try {
iifr = feature.getIncludedFeatureReferences();
} catch (CoreException e) {
UpdateUI.logException(e);
// if we can not get included features then they can not satisfy requirement, so just ignore them
return false;
}
if (iifr == null) {
return false;
}
for(int i = 0; i < iifr.length; i++) {
IFeature current;
try {
current = UpdateUtils.getIncludedFeature(feature, iifr[i]);
} catch (CoreException e) {
// if we can not get feature then it can not satisfy requirement, so just ignore it
UpdateUI.logException(e);
continue;
}
if (!visitedFeatures.contains(current)) {
visitedFeatures.add(current);
if (isFeatureGood(prereq, current, visitedFeatures)) {
return true;
}
}
}
return false;
}
int rule = (prereq.getRule() != IImport.RULE_NONE) ? prereq.getRule() : IImport.RULE_COMPATIBLE;
switch (rule) {
case IImport.RULE_PERFECT: return feature.getVersionedIdentifier().getVersion().isPerfect(
prereq.getVersionedIdentifier()
.getVersion());
case IImport.RULE_EQUIVALENT:
return feature.getVersionedIdentifier().getVersion()
.isEquivalentTo(
prereq.getVersionedIdentifier()
.getVersion());
case IImport.RULE_COMPATIBLE:
return feature.getVersionedIdentifier().getVersion()
.isCompatibleWith(
prereq.getVersionedIdentifier()
.getVersion());
case IImport.RULE_GREATER_OR_EQUAL:
return feature.getVersionedIdentifier().getVersion()
.isGreaterOrEqualTo(
prereq.getVersionedIdentifier()
.getVersion());
}
return false;
} else {
if ((prereq.getKind() == IImport.KIND_PLUGIN)) {
return checkIfFeatureHasPlugin( prereq, feature);
}
return false;
}
}
private boolean checkIfFeatureHasPlugin(IImport requiredFeature, IFeature feature) {
IPluginEntry[] plugins = feature.getPluginEntries();
try {
List includedPlugins = getPluginEntriesFromIncludedFeatures(feature, new ArrayList(), new ArrayList());
includedPlugins.addAll(Arrays.asList(plugins));
plugins = (IPluginEntry[])includedPlugins.toArray( new IPluginEntry[includedPlugins.size()]);
} catch( CoreException ce) {
UpdateUI.logException(ce);
// ignore this plugins can not sutisfy requirement anyways
}
if (plugins == null) {
return false;
}
for(int i = 0; i < plugins.length; i++) {
if (isMatch(plugins[i].getVersionedIdentifier(), requiredFeature.getVersionedIdentifier(), requiredFeature.getIdRule())) {
return true;
}
}
return false;
}
private List getPluginEntriesFromIncludedFeatures(IFeature feature, List plugins, List visitedFeatures) throws CoreException {
IIncludedFeatureReference[] iifr = feature.getIncludedFeatureReferences();
for(int i = 0; i < iifr.length; i++) {
IFeature current = UpdateUtils.getIncludedFeature( feature, iifr[i]);
if (!visitedFeatures.contains(current)) {
IPluginEntry[] pluginEntries = current.getPluginEntries();
plugins.addAll(Arrays.asList(pluginEntries));
visitedFeatures.add(current);
getPluginEntriesFromIncludedFeatures(current, plugins, visitedFeatures);
}
}
return plugins;
}
// vid1 = feature
// vid2 = requiredFeature
private boolean isMatch( VersionedIdentifier vid1, VersionedIdentifier vid2, int rule) {
if (!vid1.getIdentifier().equals(vid2.getIdentifier())) {
return false;
}
if ( vid2.getVersion().getMajorComponent() == 0 && vid2.getVersion().getMinorComponent() == 0 && vid2.getVersion().getServiceComponent() == 0 ) {
//version is ignored
return true;
}
switch (rule) {
case IImport.RULE_PERFECT:
return vid1.getVersion().isPerfect(vid2.getVersion());
case IImport.RULE_EQUIVALENT:
return vid1.getVersion().isEquivalentTo(vid2.getVersion());
case IImport.RULE_COMPATIBLE:
return vid1.getVersion().isCompatibleWith(vid2.getVersion());
case IImport.RULE_GREATER_OR_EQUAL:
return vid1.getVersion().isGreaterOrEqualTo(vid2.getVersion());
}
return false;
}
public boolean isFeatureBetter(IInstallFeatureOperation feature,
IInstallFeatureOperation currentFeatureSelected) {
if (currentFeatureSelected == null)
return true;
// If the feature is the same, pick the newer one
if (currentFeatureSelected.getFeature().getVersionedIdentifier().getIdentifier().equals(
feature.getFeature().getVersionedIdentifier().getIdentifier())) {
return !currentFeatureSelected.getFeature().getVersionedIdentifier()
.getVersion().isGreaterOrEqualTo(
feature.getFeature().getVersionedIdentifier()
.getVersion());
}
else {
// Different features.
// Pick a feature with smaller number of plug-ins
NullProgressMonitor monitor = new NullProgressMonitor();
int currentNumber = getTotalNumberOfPluginEntries(currentFeatureSelected.getFeature(), monitor);
int newNumber = getTotalNumberOfPluginEntries(feature.getFeature(), monitor);
return newNumber<currentNumber;
}
}
private int getTotalNumberOfPluginEntries(IFeature feature, IProgressMonitor monitor) {
int count = 0;
try {
count = feature.getPluginEntryCount();
IIncludedFeatureReference [] irefs = feature.getIncludedFeatureReferences();
for (int i=0; i<irefs.length; i++) {
IFeature child = irefs[i].getFeature(monitor);
count += getTotalNumberOfPluginEntries(child, monitor);
}
}
catch (CoreException e) {
}
return count;
}
public IInstallFeatureOperation decideOnFeatureSelection(
IImport requiredFeature, IInstallFeatureOperation feature,
IInstallFeatureOperation currentFeatureSelected) {
if (isFeatureGood(requiredFeature, feature.getFeature()) && isFeatureBetter(feature, currentFeatureSelected)) {
return feature;
} else {
return currentFeatureSelected;
}
}
private boolean isFeatureProblematic(IFeature feature) {
if ( problematicFeatures.contains(feature) )
return true;
IImport[] iimports = feature.getImports();
for(int i = 0; i < iimports.length; i++) {
Iterator problematicFeatures = this.problematicFeatures.iterator();
while(problematicFeatures.hasNext()) {
if (iimports[i].getVersionedIdentifier().equals( ((IFeature)problematicFeatures.next()).getVersionedIdentifier()) ) {
return true;
}
}
}
try {
Iterator includedFeatures = OperationValidator.computeFeatureSubtree(feature, null, null, false, new ArrayList(), null ).iterator();
while (includedFeatures.hasNext()) {
Iterator problematicFeatures = this.problematicFeatures.iterator();
VersionedIdentifier currentIncludedFeaturesVI = ((IFeature)includedFeatures.next()).getVersionedIdentifier();
while (problematicFeatures.hasNext()) {
Object currentProblematicFeatures = problematicFeatures.next();
if (currentProblematicFeatures instanceof IFeature) {
VersionedIdentifier currentProblematicFeaturesVI = ((IFeature)currentProblematicFeatures).getVersionedIdentifier();
if (currentProblematicFeaturesVI.equals( currentIncludedFeaturesVI) ) {
return true;
}
}
}
}
} catch (CoreException ce) {
}
return false;
}
private boolean isSelected( IInstallFeatureOperation[] selectedJobs, IInstallFeatureOperation iInstallFeatureOperation) {
if (selectedJobs == null)
return false;
for( int i = 0; i < selectedJobs.length; i++) {
if (iInstallFeatureOperation.getFeature().getVersionedIdentifier().equals(selectedJobs[i].getFeature().getVersionedIdentifier()) &&
iInstallFeatureOperation.getFeature().getSite().getURL().equals(selectedJobs[i].getFeature().getSite().getURL())) {
return true;
}
}
return false;
}
}