blob: 2f29fa3309c336f456662c40476899c1995cda31 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2017 Rapicorp 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:
* Rapicorp Corporation - initial API and implementation
* Lars Vogel <Lars.Vogel@vogella.com> - Bug 487988
* Martin Karpisek <martin.karpisek@gmail.com> - Bug 351356
*******************************************************************************/
package org.eclipse.pde.internal.ui.editor.category;
import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.viewers.*;
import org.eclipse.jface.window.Window;
import org.eclipse.pde.core.IModelChangedEvent;
import org.eclipse.pde.core.IWritable;
import org.eclipse.pde.core.plugin.*;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.pde.internal.core.ifeature.*;
import org.eclipse.pde.internal.core.isite.*;
import org.eclipse.pde.internal.ui.PDEPlugin;
import org.eclipse.pde.internal.ui.PDEUIMessages;
import org.eclipse.pde.internal.ui.dialogs.FeatureSelectionDialog;
import org.eclipse.pde.internal.ui.dialogs.PluginSelectionDialog;
import org.eclipse.pde.internal.ui.editor.*;
import org.eclipse.pde.internal.ui.editor.feature.FeatureEditor;
import org.eclipse.pde.internal.ui.editor.plugin.ManifestEditor;
import org.eclipse.pde.internal.ui.parts.FormEntry;
import org.eclipse.pde.internal.ui.parts.TablePart;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.osgi.framework.Version;
public class DownloadStatsSection extends TableSection {
private FormEntry fURLEntry;
private TableViewer fArtifactTable;
private ISiteModel fModel;
class ArtifactsContentProvider implements IStructuredContentProvider {
@Override
public Object[] getElements(Object inputElement) {
// model = (IStatsInfo) inputElement;
ArrayList<IWritable> result = new ArrayList<>();
IStatsInfo info = (IStatsInfo) inputElement;
ISiteFeature[] features = info.getFeatureArtifacts();
for (ISiteFeature feature : features) {
result.add(new SiteFeatureAdapter(null, feature));
}
ISiteBundle[] bundles = info.getBundleArtifacts();
for (ISiteBundle bundle : bundles) {
result.add(new SiteBundleAdapter(null, bundle));
}
return result.toArray();
}
}
public DownloadStatsSection(PDEFormPage page, Composite parent) {
super(page, parent, Section.DESCRIPTION, getButtonLabels());
createClient(getSection(), page.getEditor().getToolkit());
}
private static String[] getButtonLabels() {
String[] labels = new String[4];
labels[0] = PDEUIMessages.StatsSection_addFeature;
labels[1] = PDEUIMessages.StatsSection_addBundle;
labels[2] = PDEUIMessages.StatsSection_remove;
labels[3] = PDEUIMessages.StatsSection_removeAll;
return labels;
}
@Override
protected void createClient(Section section, FormToolkit toolkit) {
fModel = (ISiteModel) getPage().getModel();
fModel.addModelChangedListener(this);
section.setLayout(FormLayoutFactory.createClearGridLayout(false, 1));
GridData data = new GridData(GridData.FILL_BOTH);
section.setLayoutData(data);
// Create and configure client
Composite client = toolkit.createComposite(section);
client.setLayout(FormLayoutFactory.createSectionClientGridLayout(false, 1));
client.setLayoutData(new GridData(GridData.FILL_BOTH));
Composite urlContainer = toolkit.createComposite(client);
urlContainer.setLayout(FormLayoutFactory.createSectionClientGridLayout(false, 2));
urlContainer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// Create form entry
IActionBars actionBars = getPage().getPDEEditor().getEditorSite().getActionBars();
fURLEntry = new FormEntry(urlContainer, toolkit, PDEUIMessages.StatsSection_url, SWT.NONE);
fURLEntry.setFormEntryListener(new FormEntryAdapter(this, actionBars) {
@Override
public void textValueChanged(FormEntry entry) {
try {
getStatsInfo().setURL(entry.getValue());
} catch (CoreException e) {
PDEPlugin.log(e);
}
}
});
fURLEntry.setEditable(isEditable());
Composite container = createClientContainer(client, 2, toolkit);
createViewerPartControl(container, SWT.MULTI, 2, toolkit);
container.setLayoutData(new GridData(GridData.FILL_BOTH));
TablePart tablePart = getTablePart();
fArtifactTable = tablePart.getTableViewer();
fArtifactTable.setContentProvider(new ArtifactsContentProvider());
fArtifactTable.setLabelProvider(new CategoryLabelProvider());
fArtifactTable.setComparator(new ViewerComparator() {
@Override
public int category(Object element) {
if (element instanceof SiteFeatureAdapter)
return 0;
return 1;
}
});
data = (GridData) tablePart.getControl().getLayoutData();
data.minimumWidth = 200;
fArtifactTable.setInput(getStatsInfo());
tablePart.setButtonEnabled(0, isEditable());
tablePart.setButtonEnabled(1, isEditable());
tablePart.setButtonEnabled(2, isEditable());
tablePart.setButtonEnabled(3, isEditable());
toolkit.paintBordersFor(container);
section.setClient(client);
section.setText(PDEUIMessages.StatsSection_title);
section.setDescription(PDEUIMessages.StatsSection_description);
}
@Override
protected void buttonSelected(int index) {
switch (index) {
case 0 :
handleNewFeature();
break;
case 1 :
handleNewBundle();
break;
case 2 :
handleRemove();
break;
case 3 :
handleRemoveAll();
break;
}
}
private void handleRemove() {
IStructuredSelection ssel = fArtifactTable.getStructuredSelection();
Iterator<?> iterator = ssel.iterator();
while (iterator.hasNext()) {
Object object = iterator.next();
if (object == null)
continue;
if (object instanceof SiteFeatureAdapter) {
handleRemoveSiteFeatureAdapter((SiteFeatureAdapter) object);
} else if (object instanceof SiteBundleAdapter) {
handleRemoveSiteBundleAdapter((SiteBundleAdapter) object);
}
}
}
private boolean handleRemoveSiteFeatureAdapter(SiteFeatureAdapter adapter) {
try {
ISiteFeature feature = adapter.feature;
getStatsInfo().removeFeatureArtifacts(new ISiteFeature[] {feature});
return true;
} catch (CoreException e) {
}
return false;
}
private boolean handleRemoveSiteBundleAdapter(SiteBundleAdapter adapter) {
try {
ISiteBundle bundle = adapter.bundle;
getStatsInfo().removeBundleArtifacts(new ISiteBundle[] {bundle});
return true;
} catch (CoreException e) {
}
return false;
}
private void handleRemoveAll() {
try {
getStatsInfo().removeBundleArtifacts(getStatsInfo().getBundleArtifacts());
getStatsInfo().removeFeatureArtifacts(getStatsInfo().getFeatureArtifacts());
} catch (CoreException e) {
PDEPlugin.log(e);
}
fArtifactTable.refresh(false);
updateButtons();
}
@Override
protected void handleDoubleClick(IStructuredSelection ssel) {
super.handleDoubleClick(ssel);
Object selected = ssel.getFirstElement();
if (selected instanceof SiteFeatureAdapter) {
IFeature feature = findFeature(((SiteFeatureAdapter) selected).feature);
FeatureEditor.openFeatureEditor(feature);
} else if (selected instanceof SiteBundleAdapter) {
ManifestEditor.openPluginEditor(((SiteBundleAdapter) selected).bundle.getId());
}
}
@Override
public boolean doGlobalAction(String actionId) {
if (actionId.equals(ActionFactory.DELETE.getId())) {
handleRemove();
return true;
}
if (actionId.equals(ActionFactory.CUT.getId())) {
handleRemove();
return false;
}
return super.doGlobalAction(actionId);
}
/**
* Finds a feature with the same id and version as a site feature. If
* feature is not found, but feature with a M.m.s.qualifier exists it will
* be returned.
*
* @param siteFeature
* @return IFeature or null
*/
private IFeature findFeature(ISiteFeature siteFeature) {
IFeatureModel model = PDECore.getDefault().getFeatureModelManager().findFeatureModelRelaxed(siteFeature.getId(), siteFeature.getVersion());
if (model != null)
return model.getFeature();
return null;
}
private void handleNewFeature() {
final Control control = fArtifactTable.getControl();
BusyIndicator.showWhile(control.getDisplay(), () -> {
IFeatureModel[] allModels = PDECore.getDefault().getFeatureModelManager().getModels();
ArrayList<IFeatureModel> newModels = new ArrayList<>();
for (IFeatureModel allModel : allModels) {
if (canAdd(allModel))
newModels.add(allModel);
}
IFeatureModel[] candidateModels = newModels.toArray(new IFeatureModel[newModels.size()]);
FeatureSelectionDialog dialog = new FeatureSelectionDialog(fArtifactTable.getTable().getShell(), candidateModels, true);
if (dialog.open() == Window.OK) {
Object[] models = dialog.getResult();
try {
doAddFeatures(models);
} catch (CoreException e) {
PDEPlugin.log(e);
}
}
});
}
private void handleNewBundle() {
final Control control = fArtifactTable.getControl();
BusyIndicator.showWhile(control.getDisplay(), () -> {
IPluginModelBase[] allModels = PluginRegistry.getAllModels();
ArrayList<IPluginModelBase> newModels = new ArrayList<>();
for (IPluginModelBase allModel : allModels) {
if (canAdd(allModel))
newModels.add(allModel);
}
IPluginModelBase[] candidateModels = newModels.toArray(new IPluginModelBase[newModels.size()]);
PluginSelectionDialog dialog = new PluginSelectionDialog(fArtifactTable.getTable().getShell(), candidateModels, true);
if (dialog.open() == Window.OK) {
Object[] models = dialog.getResult();
try {
doAddBundles(models);
} catch (CoreException e) {
PDEPlugin.log(e);
}
}
});
}
private boolean canAdd(IFeatureModel candidate) {
ISiteFeature[] features = fModel.getSite().getStatsInfo().getFeatureArtifacts();
IFeature cfeature = candidate.getFeature();
for (ISiteFeature bfeature : features) {
if (bfeature.getId().equals(cfeature.getId()) && bfeature.getVersion().equals(cfeature.getVersion()))
return false;
}
return true;
}
private boolean canAdd(IPluginModelBase candidate) {
ISiteBundle[] currentBundles = fModel.getSite().getStatsInfo().getBundleArtifacts();
IPluginBase candidateBundle = candidate.getPluginBase();
for (ISiteBundle currentBundle : currentBundles) {
if (currentBundle.getId().equals(candidateBundle.getId()) && currentBundle.getVersion().equals(candidateBundle.getVersion()))
return false;
}
return true;
}
private ISiteFeature createSiteFeature(ISiteModel model, IFeatureModel featureModel) throws CoreException {
IFeature feature = featureModel.getFeature();
ISiteFeature sfeature = model.getFactory().createFeature();
sfeature.setId(feature.getId());
sfeature.setVersion(feature.getVersion());
// sfeature.setURL(model.getBuildModel().getSiteBuild().getFeatureLocation()
// + "/" + feature.getId() + "_" + feature.getVersion() + ".jar");
// //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
sfeature.setURL("features/" + feature.getId() + "_" + formatVersion(feature.getVersion()) + ".jar"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
sfeature.setOS(feature.getOS());
sfeature.setWS(feature.getWS());
sfeature.setArch(feature.getArch());
sfeature.setNL(feature.getNL());
sfeature.setIsPatch(isFeaturePatch(feature));
return sfeature;
}
private ISiteBundle createSiteBundle(ISiteModel model, IPluginModelBase candidate) throws CoreException {
ISiteBundle newBundle = model.getFactory().createBundle();
newBundle.setId(candidate.getPluginBase().getId());
newBundle.setVersion(candidate.getPluginBase().getVersion());
return newBundle;
}
private String formatVersion(String version) {
try {
Version v = new Version(version);
return v.toString();
} catch (IllegalArgumentException e) {
}
return version;
}
private boolean isFeaturePatch(IFeature feature) {
IFeatureImport[] imports = feature.getImports();
for (IFeatureImport import1 : imports) {
if (import1.isPatch())
return true;
}
return false;
}
/**
* @param candidates Array of IFeatureModel
*/
public void doAddFeatures(Object[] candidates) throws CoreException {
ISiteFeature[] added = new ISiteFeature[candidates.length];
for (int i = 0; i < candidates.length; i++) {
IFeatureModel candidate = (IFeatureModel) candidates[i];
ISiteFeature child = createSiteFeature(fModel, candidate);
added[i] = child;
}
// Update model
getStatsInfo().addFeatureArtifacts(added);
// Select last added feature
if (added.length > 0) {
fArtifactTable.setSelection(new StructuredSelection(new SiteFeatureAdapter(null, added[added.length - 1])), true);
}
}
/**
* @param candidates Array of IPluginModelBase
*/
public void doAddBundles(Object[] candidates) throws CoreException {
ISiteBundle[] added = new ISiteBundle[candidates.length];
for (int i = 0; i < candidates.length; i++) {
IPluginModelBase candidate = (IPluginModelBase) candidates[i];
ISiteBundle child = createSiteBundle(fModel, candidate);
added[i] = child;
}
// Update model
getStatsInfo().addBundleArtifacts(added);
// Select last added bundle
if (added.length > 0) {
fArtifactTable.setSelection(new StructuredSelection(new SiteBundleAdapter(null, added[added.length - 1])), true);
}
}
@Override
protected void selectionChanged(IStructuredSelection selection) {
getPage().getPDEEditor().setSelection(selection);
updateButtons();
}
@Override
public void refresh() {
IStatsInfo info = getStatsInfo();
fURLEntry.setValue(info.getURL(), true);
fArtifactTable.refresh();
super.refresh();
}
@Override
public void commit(boolean onSave) {
fURLEntry.commit();
super.commit(onSave);
}
@Override
public void cancelEdit() {
fURLEntry.cancelEdit();
super.cancelEdit();
}
private IStatsInfo getStatsInfo() {
IStatsInfo info = getSite().getStatsInfo();
if (info == null) {
info = getModel().getFactory().createStatsInfo();
try {
getSite().setStatsInfo(info);
} catch (CoreException e) {
PDEPlugin.log(e);
}
}
return info;
}
public ISiteModel getModel() {
return fModel;
}
public ISite getSite() {
return fModel.getSite();
}
@Override
public boolean canPaste(Clipboard clipboard) {
Display d = getSection().getDisplay();
Control c = d.getFocusControl();
if (c instanceof Text)
return true;
return false;
}
@Override
public void modelChanged(IModelChangedEvent e) {
// No need to call super, handling world changed event here
fArtifactTable.setInput(getStatsInfo());
refresh();
updateButtons();
}
@Override
public void dispose() {
ISiteModel model = getModel();
if (model != null)
model.removeModelChangedListener(this);
super.dispose();
}
private void updateButtons() {
TablePart tablePart = getTablePart();
ISelection selection = getViewerSelection();
boolean enabled = isEditable() && !selection.isEmpty() && selection instanceof IStructuredSelection;
tablePart.setButtonEnabled(2, enabled);
tablePart.setButtonEnabled(3, isEditable() && (getStatsInfo().getFeatureArtifacts().length > 0 || getStatsInfo().getBundleArtifacts().length > 0));
}
}