### Eclipse Workspace Patch 1.0 #P org.eclipse.pde.launching Index: src/org/eclipse/pde/internal/launching/launcher/BundleLauncherHelper.java =================================================================== RCS file: /cvsroot/eclipse/pde/ui/org.eclipse.pde.launching/src/org/eclipse/pde/internal/launching/launcher/BundleLauncherHelper.java,v retrieving revision 1.3 diff -u -r1.3 BundleLauncherHelper.java --- src/org/eclipse/pde/internal/launching/launcher/BundleLauncherHelper.java 1 Feb 2010 18:40:47 -0000 1.3 +++ src/org/eclipse/pde/internal/launching/launcher/BundleLauncherHelper.java 16 Feb 2010 12:55:33 -0000 @@ -19,7 +19,6 @@ import org.eclipse.pde.core.plugin.*; import org.eclipse.pde.internal.build.IPDEBuildConstants; import org.eclipse.pde.internal.core.*; -import org.eclipse.pde.internal.core.feature.FeaturePlugin; import org.eclipse.pde.internal.core.ifeature.*; import org.eclipse.pde.internal.launching.IPDEConstants; import org.eclipse.pde.launching.IPDELauncherConstants; @@ -27,6 +26,9 @@ public class BundleLauncherHelper { public static final char VERSION_SEPARATOR = '*'; + private static final String LOCATION_DEFAULT = "Default"; //$NON-NLS-1$ + private static final String LOCATION_EXTERNAL = "External"; //$NON-NLS-1$ + private static final String LOCATION_WORKSPACE = "Workspace"; //$NON-NLS-1$ public static Map getWorkspaceBundleMap(ILaunchConfiguration configuration) throws CoreException { return getWorkspaceBundleMap(configuration, null, IPDELauncherConstants.WORKSPACE_BUNDLES); @@ -63,41 +65,59 @@ } if (configuration.getAttribute(IPDELauncherConstants.USE_CUSTOM_FEATURES, true)) { - HashMap featurelocationMap = BundleLauncherHelper.getFeatureLocationMap(configuration); - FeatureModelManager fmm = new FeatureModelManager(); - ExternalFeatureModelManager efmm = new ExternalFeatureModelManager(); + //TODO + FeatureModelManager featureModelMgr = new FeatureModelManager(); + ExternalFeatureModelManager extFeatureModelMgr = new ExternalFeatureModelManager(); - IFeatureModel[] wrkspcModels = fmm.getWorkspaceModels(); + IFeatureModel[] workspaceModels = featureModelMgr.getWorkspaceModels(); HashMap wrkspcFeaturesMap = new HashMap(); - for (int i = 0; i < wrkspcModels.length; i++) { - wrkspcFeaturesMap.put(wrkspcModels[i].getFeature().getId(), wrkspcModels[i].getFeature()); + for (int i = 0; i < workspaceModels.length; i++) { + wrkspcFeaturesMap.put(workspaceModels[i].getFeature().getId(), workspaceModels[i].getFeature()); } - efmm.startup(); - IFeatureModel[] extrnlModels = efmm.getModels(); + extFeatureModelMgr.startup(); + IFeatureModel[] externalModels = extFeatureModelMgr.getModels(); HashMap extrnlFeaturesMap = new HashMap(); - for (int i = 0; i < extrnlModels.length; i++) { - extrnlFeaturesMap.put(extrnlModels[i].getFeature().getId(), extrnlModels[i].getFeature()); + for (int i = 0; i < externalModels.length; i++) { + extrnlFeaturesMap.put(externalModels[i].getFeature().getId(), externalModels[i].getFeature()); } - efmm.shutdown(); + extFeatureModelMgr.shutdown(); - for (Iterator iterator = featurelocationMap.keySet().iterator(); iterator.hasNext();) { + HashMap featureVersionMap = new HashMap(); + HashMap featureLocationMap = new HashMap(); + HashMap pluginResolutionMap = new HashMap(); + getFeatureMaps(configuration, featureVersionMap, featureLocationMap, pluginResolutionMap); + String defaultLocation = configuration.getAttribute(IPDELauncherConstants.FEATURE_DEFAULT_LOCATION, LOCATION_WORKSPACE); + PluginModelManager pluginModelMgr = new PluginModelManager(); + for (Iterator iterator = featureLocationMap.keySet().iterator(); iterator.hasNext();) { String id = (String) iterator.next(); - String location = (String) featurelocationMap.get(id); + String location = (String) featureLocationMap.get(id); IFeature feature = null; - if (IPDELauncherConstants.LOCATION_WORKSPACE.equalsIgnoreCase(location)) { + if (LOCATION_DEFAULT.equalsIgnoreCase(location)) { + location = defaultLocation; + } + if (LOCATION_WORKSPACE.equalsIgnoreCase(location)) { feature = (IFeature) wrkspcFeaturesMap.get(id); - } else if (IPDELauncherConstants.LOCATION_EXTERNAL.equalsIgnoreCase(location)) { + } else if (LOCATION_EXTERNAL.equalsIgnoreCase(location)) { feature = (IFeature) extrnlFeaturesMap.get(id); } - if (feature == null) + if (feature == null || !feature.getVersion().equalsIgnoreCase((String) featureVersionMap.get(id))) continue; IFeaturePlugin[] featurePlugins = feature.getPlugins(); for (int i = 0; i < featurePlugins.length; i++) { - FeaturePlugin plugin = (FeaturePlugin) featurePlugins[i]; - if (plugin.getPluginBase() == null) + IPluginModelBase model = pluginModelMgr.findModel(featurePlugins[i].getId()); + if (model == null) continue; - addBundleToMap(map, plugin.getPluginBase().getPluginModel(), "default:default"); //$NON-NLS-1$ + addBundleToMap(map, model, "default:default"); //$NON-NLS-1$ + } + IFeatureImport[] featureImports = feature.getImports(); + for (int i = 0; i < featureImports.length; i++) { + if (featureImports[i].getType() == IFeatureImport.PLUGIN) { + IPluginModelBase model = pluginModelMgr.findModel(featureImports[i].getId()); + if (model == null) + continue; + addBundleToMap(map, model, "default:default"); //$NON-NLS-1$ + } } } @@ -354,22 +374,7 @@ wc.doSave(); } - public static HashMap getFeatureLocationMap(ILaunchConfiguration config) throws CoreException { - HashMap featureLocationMap = new HashMap(); - String value = config.getAttribute(IPDELauncherConstants.SELECTED_FEATURES, ""); //$NON-NLS-1$ - if (value.length() != 0) { - String[] features = value.split(";"); //$NON-NLS-1$ - if (features != null && features.length > 0) { - for (int i = 0; i < features.length; i++) { - String[] attributes = features[i].split(":"); //$NON-NLS-1$ - featureLocationMap.put(attributes[0], attributes[2]); - } - } - } - return featureLocationMap; - } - - public static String writeFeatureEntry(String id, String version, String location) { + public static String writeFeatureEntry(String id, String version, String location, String resolution) { StringBuffer buffer = new StringBuffer(); buffer.append(id); @@ -377,9 +382,38 @@ buffer.append(version); buffer.append(':'); buffer.append(location); + buffer.append(':'); + buffer.append(resolution); buffer.append(';'); return buffer.toString(); } + public static ArrayList getFeatureMaps(ILaunchConfiguration config, HashMap featureVersionMap, HashMap featureLocationMap, HashMap pluginResolutionMap) throws CoreException { + HashMap versionMap = new HashMap(); + HashMap locationMap = new HashMap(); + HashMap resolutionMap = new HashMap(); + ArrayList selectedFeatureList = new ArrayList(); + String value = config.getAttribute(IPDELauncherConstants.SELECTED_FEATURES, ""); //$NON-NLS-1$ + if (value.length() != 0) { + String[] features = value.split(";"); //$NON-NLS-1$ + if (features != null && features.length > 0) { + for (int i = 0; i < features.length; i++) { + String[] attributes = features[i].split(":"); //$NON-NLS-1$ + selectedFeatureList.add(attributes[0]); + versionMap.put(attributes[0], attributes[1]); + locationMap.put(attributes[0], attributes[2]); + resolutionMap.put(attributes[0], attributes[3]); + } + } + } + + if (featureVersionMap != null) + featureVersionMap.putAll(versionMap); + if (featureLocationMap != null) + featureLocationMap.putAll(locationMap); + if (resolutionMap != null) + pluginResolutionMap.putAll(resolutionMap); + return selectedFeatureList; + } } Index: src/org/eclipse/pde/launching/IPDELauncherConstants.java =================================================================== RCS file: /cvsroot/eclipse/pde/ui/org.eclipse.pde.launching/src/org/eclipse/pde/launching/IPDELauncherConstants.java,v retrieving revision 1.5 diff -u -r1.5 IPDELauncherConstants.java --- src/org/eclipse/pde/launching/IPDELauncherConstants.java 1 Feb 2010 18:40:48 -0000 1.5 +++ src/org/eclipse/pde/launching/IPDELauncherConstants.java 16 Feb 2010 12:55:34 -0000 @@ -402,11 +402,38 @@ */ String GENERATE_PROFILE = "generateProfile"; //$NON-NLS-1$ + /** + * Launch configuration attribute key. The value is a string specifying + * a comma-separated list of IDs of features to launch with. + * + * @since 3.6 + */ String SELECTED_FEATURES = "selected_features"; //$NON-NLS-1$ + /** + * Launch configuration attribute key. The value is a boolean specifying + * if the feature-based launching mode should be used. + * This mode will launch with all the workspace and external features + * that have been explicitly selected in the Plug-ins Tab. + * + * @since 3.6 + */ String USE_CUSTOM_FEATURES = "useCustomFeatures"; //$NON-NLS-1$ - String LOCATION_WORKSPACE = "Workspace"; //$NON-NLS-1$ + /** + * Launch configuration attribute key. The value is a String specifying + * if the default location for a feature is workspace or external. + * + * @since 3.6 + */ + String FEATURE_DEFAULT_LOCATION = "featureDefaultLocation"; //$NON-NLS-1$ - String LOCATION_EXTERNAL = "Target"; //$NON-NLS-1$ + /** + * Launch configuration attribute key. The value is a String specifying + * if the default plug-in resolution location for a feature + * is workspace or external. + * + * @since 3.6 + */ + String FEATURE_PLUGIN_RESOLUTION = "featurePluginResolution"; //$NON-NLS-1$ } #P org.eclipse.pde.ui Index: src/org/eclipse/pde/internal/ui/IPreferenceConstants.java =================================================================== RCS file: /cvsroot/eclipse/pde/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/IPreferenceConstants.java,v retrieving revision 1.31 diff -u -r1.31 IPreferenceConstants.java --- src/org/eclipse/pde/internal/ui/IPreferenceConstants.java 5 Oct 2009 22:43:14 -0000 1.31 +++ src/org/eclipse/pde/internal/ui/IPreferenceConstants.java 16 Feb 2010 12:55:37 -0000 @@ -39,4 +39,8 @@ public static final String DEPS_VIEW_SHOW_CALLERS = "DependenciesView.show.callers"; //$NON-NLS-1$ public static final String DEPS_VIEW_SHOW_LIST = "DependenciesView.show.list"; //$NON-NLS-1$ public static final String DEPS_VIEW_SHOW_STATE = "DependenciesView.show.state"; //$NON-NLS-1$ + + //Run Configurations - Plug-ins Tab - Feature launching + public static final String FEATURE_SORT_COLUMN = "Preferences.RunConfigs.Feature.SortColumn"; //$NON-NLS-1$ + public static final String FEATURE_SORT_ORDER = "Preferences.RunConfigs.Feature.SortOrder"; //$NON-NLS-1$ } Index: src/org/eclipse/pde/internal/ui/PDEUIMessages.java =================================================================== RCS file: /cvsroot/eclipse/pde/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java,v retrieving revision 1.456 diff -u -r1.456 PDEUIMessages.java --- src/org/eclipse/pde/internal/ui/PDEUIMessages.java 1 Feb 2010 18:41:01 -0000 1.456 +++ src/org/eclipse/pde/internal/ui/PDEUIMessages.java 16 Feb 2010 12:55:39 -0000 @@ -66,13 +66,21 @@ public static String FeatureBlock_addRequiredFeatues; + public static String FeatureBlock_default; + + public static String FeatureBlock_defaultFeatureLocation; + + public static String FeatureBlock_defaultPluginResolution; + public static String FeatureBlock_features; - public static String FeatureBlock_location; + public static String FeatureBlock_featureLocation; + + public static String FeatureBlock_pluginResolution; public static String FeatureBlock_showSelected; - public static String FeatureBlock_external; + public static String FeatureBlock_externalBefore; public static String FeatureBlock_useExternalFeatures; @@ -80,7 +88,7 @@ public static String FeatureBlock_version; - public static String FeatureBlock_workspace; + public static String FeatureBlock_workspaceBefore; public static String FeatureEditor_exportTooltip; Index: src/org/eclipse/pde/internal/ui/pderesources.properties =================================================================== RCS file: /cvsroot/eclipse/pde/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties,v retrieving revision 1.1111 diff -u -r1.1111 pderesources.properties --- src/org/eclipse/pde/internal/ui/pderesources.properties 1 Feb 2010 18:41:02 -0000 1.1111 +++ src/org/eclipse/pde/internal/ui/pderesources.properties 16 Feb 2010 12:55:40 -0000 @@ -104,14 +104,18 @@ ######## Feature Manifest Editor #################### FeatureBlock_addRequiedBundles=Add Required Bundles FeatureBlock_addRequiredFeatues=Add Required Features +FeatureBlock_default=Default +FeatureBlock_defaultFeatureLocation=Default Feature Location +FeatureBlock_defaultPluginResolution=Default Plug-in Resolution FeatureBlock_features=Features -FeatureBlock_location=Location +FeatureBlock_featureLocation=Feature location +FeatureBlock_pluginResolution=Plug-in resolution FeatureBlock_showSelected=Only show selected Features -FeatureBlock_external=External +FeatureBlock_externalBefore=External before Workspace FeatureBlock_useExternalFeatures=Use External Features FeatureBlock_useWorkspaceFeatures=Use Workspace Features FeatureBlock_version=Version -FeatureBlock_workspace=Workspace +FeatureBlock_workspaceBefore=Workspace before External FeatureEditor_BuildAction_label = &Export... FeatureEditor_FeaturePage_title = Overview FeatureEditor_InfoPage_title = Information Index: src/org/eclipse/pde/internal/ui/launcher/FeatureBlock.java =================================================================== RCS file: /cvsroot/eclipse/pde/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/launcher/FeatureBlock.java,v retrieving revision 1.1 diff -u -r1.1 FeatureBlock.java --- src/org/eclipse/pde/internal/ui/launcher/FeatureBlock.java 1 Feb 2010 18:40:57 -0000 1.1 +++ src/org/eclipse/pde/internal/ui/launcher/FeatureBlock.java 16 Feb 2010 12:55:41 -0000 @@ -17,9 +17,9 @@ import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.jface.viewers.*; import org.eclipse.osgi.util.NLS; -import org.eclipse.pde.internal.core.FeatureModelManager; -import org.eclipse.pde.internal.core.ifeature.IFeature; -import org.eclipse.pde.internal.core.ifeature.IFeatureModel; +import org.eclipse.pde.internal.core.*; +import org.eclipse.pde.internal.core.ifeature.*; +import org.eclipse.pde.internal.core.util.VersionUtil; import org.eclipse.pde.internal.launching.launcher.BundleLauncherHelper; import org.eclipse.pde.internal.ui.*; import org.eclipse.pde.internal.ui.elements.DefaultContentProvider; @@ -30,31 +30,15 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; +import org.osgi.framework.Version; public class FeatureBlock { - private ILaunchConfiguration fLaunchConfig; - private AbstractLauncherTab fTab; - private CheckboxTableViewer fViewer; - private Table fTable; - private Button fSelectAllButton; - private Button fDeselectAllButton; - private Button fUseWrkSpcFeaturesButton; - private Button fUseExtrnlFeaturesButton; - private Button fDefaultsButton; - private Button fFilterButton; - private Label fCounter; - private Listener fListener; - private HashMap fWorkspaceFeatureMap; - private HashMap fExternalFeatureMap; - private HashMap fFeatureLocationMap; - - private static final String COLUMN_ID = "columnID"; //$NON-NLS-1$ - class FeatureTableLabelProvider extends PDELabelProvider { public Image getColumnImage(Object obj, int index) { return index == 0 ? super.getColumnImage(obj, index) : null; @@ -62,33 +46,22 @@ public String getColumnText(Object obj, int index) { switch (index) { - case 0 : - return super.getObjectText((IFeatureModel) obj, false); - case 1 : - IFeature feature = ((IFeatureModel) obj).getFeature(); - return feature.getVersion(); - - case 2 : - String location = (String) fFeatureLocationMap.get(((IFeatureModel) obj).getFeature().getId()); - if (IPDELauncherConstants.LOCATION_WORKSPACE.equalsIgnoreCase(location)) { - return PDEUIMessages.FeatureBlock_workspace; - } else if (IPDELauncherConstants.LOCATION_EXTERNAL.equalsIgnoreCase(location)) { - return PDEUIMessages.FeatureBlock_external; - } - return ""; //$NON-NLS-1$ + case COLUMN_FEATURE_NAME : + return super.getObjectText((IFeatureModel) fFeatureModelMap.get(obj), false); + case COLUMN_FEATURE_VERSION : + return (String) fFeatureVersionMap.get(obj); + case COLUMN_FEATURE_LOCATION : + String featureLocation = (String) fFeatureLocationMap.get(obj); + return getLocationText(featureLocation); + case COLUMN_PLUGIN_RESOLUTION : + String pluginResolution = (String) fPluginResolutionMap.get(obj); + return getLocationText(pluginResolution); default : return ""; //$NON-NLS-1$ } } } - class PluginContentProvider extends DefaultContentProvider implements IStructuredContentProvider { - - public Object[] getElements(Object input) { - return (IFeatureModel[]) input; - } - } - class Listener extends SelectionAdapter { public void widgetSelected(SelectionEvent e) { @@ -97,56 +70,185 @@ handleSelectAll(true); } else if (source == fDeselectAllButton) { handleSelectAll(false); - } else if (source == fUseWrkSpcFeaturesButton) { - handleUseLocation(fWorkspaceFeatureMap, IPDELauncherConstants.LOCATION_WORKSPACE); - } else if (source == fUseExtrnlFeaturesButton) { - handleUseLocation(fExternalFeatureMap, IPDELauncherConstants.LOCATION_EXTERNAL); + } else if (source == fAddRequiredFeaturesButton) { + handleAddRequired(); } else if (source == fDefaultsButton) { handleRestoreDefaults(); + } else if (source == fDefaultFeatureLocationCombo) { + handleDefaultChange(); } else if (source instanceof TableColumn) { - handleColumn((TableColumn) source); + handleColumn((TableColumn) source, 0); } fTab.updateLaunchConfigurationDialog(); } - private void handleColumn(TableColumn tc) { + private void handleAddRequired() { + if (fViewer.getCheckedElements() != null && fViewer.getCheckedElements().length > 0) { + Object[] featureModelIDs = fViewer.getCheckedElements(); + ArrayList requiredFeatureList = new ArrayList(); + + for (int i = 0; i < featureModelIDs.length; i++) { + requiredFeatureList.add(featureModelIDs[i]); + getFeatureDependencies((IFeatureModel) fFeatureModelMap.get(featureModelIDs[i]), requiredFeatureList); + } + fViewer.setCheckedElements(requiredFeatureList.toArray()); + } + } + + private void getFeatureDependencies(IFeatureModel model, ArrayList requiredFeatureList) { + IFeature feature = model.getFeature(); + IFeatureImport[] featureImports = feature.getImports(); + for (int i = 0; i < featureImports.length; i++) { + if (featureImports[i].getType() == IFeatureImport.FEATURE) { + addFeature(requiredFeatureList, featureImports[i].getId()); + } + } + + IFeatureChild[] featureIncludes = feature.getIncludedFeatures(); + for (int i = 0; i < featureIncludes.length; i++) { + addFeature(requiredFeatureList, featureIncludes[i].getId()); + } + } + + private void addFeature(ArrayList requiredFeatureList, String id) { + IFeatureModel model; + if (!requiredFeatureList.contains(id)) { + model = (IFeatureModel) fFeatureModelMap.get(id); + if (model != null) { + requiredFeatureList.add(id); + getFeatureDependencies(model, requiredFeatureList); + } + } + } + + private void handleColumn(TableColumn tc, int sortDirn) { fTable.setSortColumn(tc); - int sortDirn; - switch (fTable.getSortDirection()) { - case SWT.DOWN : - sortDirn = SWT.UP; - break; - case SWT.UP : - default : - sortDirn = SWT.DOWN; + if (sortDirn == 0) { + switch (fTable.getSortDirection()) { + case SWT.DOWN : + sortDirn = SWT.UP; + break; + case SWT.UP : + default : + sortDirn = SWT.DOWN; + } } fTable.setSortDirection(sortDirn); int sortOrder = sortDirn == SWT.UP ? 1 : -1; int sortColumn = ((Integer) tc.getData(COLUMN_ID)).intValue(); fViewer.setSorter(new TableSorter(sortColumn, sortOrder)); + saveSortOrder(); } private void handleRestoreDefaults() { - fViewer.setInput(getFeatures()); + fDefaultFeatureLocationCombo.setText(getLocationText(LOCATION_WORKSPACE)); + fDefaultPluginResolutionCombo.setText(getLocationText(LOCATION_WORKSPACE)); + fViewer.setInput(getFeatures(LOCATION_WORKSPACE)); + fViewer.refresh(true); + } + + private void handleSelectAll(boolean state) { + fViewer.setAllChecked(state); + updateCounter(); + fViewer.refresh(true); + } + + private void handleDefaultChange() { + String defaultLocation = getLocationConstant(fDefaultFeatureLocationCombo.getText()); + for (Iterator iterator = fFeatureModelMap.keySet().iterator(); iterator.hasNext();) { + String id = (String) iterator.next(); + String location = (String) fFeatureLocationMap.get(id); + if (LOCATION_DEFAULT.equalsIgnoreCase(location)) { + IFeatureModel model = null; + if (LOCATION_WORKSPACE.equalsIgnoreCase(defaultLocation)) { + model = (IFeatureModel) fWorkspaceFeatureMap.get(id); + } else { + model = (IFeatureModel) fExternalFeatureMap.get(id); + } + if (model != null) { + fFeatureModelMap.put(id, model); + fFeatureVersionMap.put(id, model.getFeature().getVersion()); + fViewer.refresh(id, true); + } + } + } } + } - private void handleUseLocation(HashMap featureMap, String location) { - IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection(); - if (selection.isEmpty()) - return; - Object[] models = selection.toArray(); - for (int i = 0; i < models.length; i++) { - String id = ((IFeatureModel) models[i]).getFeature().getId(); - if (featureMap.containsKey(id)) { - fFeatureLocationMap.put(id, location); - fViewer.refresh(models[i], true); + private class LocationCellModifier implements ICellModifier { + + public boolean canModify(Object id, String property) { + if (PROPERTY_LOCATION.equalsIgnoreCase(property)) { + if (fWorkspaceFeatureMap.containsKey(id) && fExternalFeatureMap.containsKey(id)) { + return fViewer.getChecked(id); } + + } else if (PROPERTY_RESOLUTION.equalsIgnoreCase(property)) { + return true; } + return false; } - private void handleSelectAll(boolean state) { - fViewer.setAllChecked(state); - updateCounter(); + public Object getValue(Object id, String property) { + if (PROPERTY_LOCATION.equalsIgnoreCase(property) || PROPERTY_RESOLUTION.equalsIgnoreCase(property)) { + String location = (String) fFeatureLocationMap.get(id); + + if (LOCATION_DEFAULT.equalsIgnoreCase(location)) { + return new Integer(0); + } else if (LOCATION_WORKSPACE.equalsIgnoreCase(location)) { + return new Integer(1); + } else if (LOCATION_EXTERNAL.equalsIgnoreCase(location)) { + return new Integer(2); + } + } + + return new Integer(0); + } + + public void modify(Object item, String property, Object value) { + String id = (String) ((TableItem) item).getData(); + int comboIndex = ((Integer) value).intValue(); + String location = null; + HashMap map = null; + switch (comboIndex) { + case 0 : + location = LOCATION_DEFAULT; + if (LOCATION_WORKSPACE.equalsIgnoreCase(getLocationConstant(fDefaultFeatureLocationCombo.getText()))) { + map = fWorkspaceFeatureMap; + } else { + map = fExternalFeatureMap; + } + break; + case 1 : + location = LOCATION_WORKSPACE; + map = fWorkspaceFeatureMap; + break; + case 2 : + location = LOCATION_EXTERNAL; + map = fExternalFeatureMap; + } + + if (PROPERTY_LOCATION.equalsIgnoreCase(property)) { + fFeatureLocationMap.put(id, location); + IFeatureModel newModel = (IFeatureModel) map.get(id); + fFeatureVersionMap.put(id, newModel.getFeature().getVersion()); + fFeatureModelMap.put(id, newModel); + } else if (PROPERTY_RESOLUTION.equalsIgnoreCase(property)) { + fPluginResolutionMap.put(id, location); + + } else { + return; // nothing to do + } + + fViewer.refresh(id, true); + fTab.updateLaunchConfigurationDialog(); + } + } + + class PluginContentProvider extends DefaultContentProvider implements IStructuredContentProvider { + + public Object[] getElements(Object input) { + return (String[]) input; } } @@ -169,65 +271,52 @@ } - private class LocationCellModifier implements ICellModifier { + private static final int COLUMN_FEATURE_NAME = 0; + private static final int COLUMN_FEATURE_VERSION = 1; + private static final int COLUMN_FEATURE_LOCATION = 2; + private static final int COLUMN_PLUGIN_RESOLUTION = 3; - public boolean canModify(Object element, String property) { - if (element instanceof IFeatureModel) { - IFeature feature = ((IFeatureModel) element).getFeature(); - if (IPDELauncherConstants.LOCATION.equalsIgnoreCase(property)) { - if (fWorkspaceFeatureMap.containsKey(feature.getId()) && fExternalFeatureMap.containsKey(feature.getId())) { - return true; - } - } - } - return false; - } + private static final String COLUMN_ID = "columnID"; //$NON-NLS-1$ - public Object getValue(Object element, String property) { - if (element instanceof IFeatureModel) { - if (IPDELauncherConstants.LOCATION.equalsIgnoreCase(property)) { - IFeature feature = ((IFeatureModel) element).getFeature(); - String location = (String) fFeatureLocationMap.get(feature.getId()); - if (IPDELauncherConstants.LOCATION_WORKSPACE.equalsIgnoreCase(location)) { - return new Integer(0); - } else if (IPDELauncherConstants.LOCATION_EXTERNAL.equalsIgnoreCase(location)) { - return new Integer(1); - } - } - } - return new Integer(0); - } + private static final String LOCATION_DEFAULT = "Default"; //$NON-NLS-1$ + private static final String LOCATION_EXTERNAL = "External"; //$NON-NLS-1$ + private static final String LOCATION_WORKSPACE = "Workspace"; //$NON-NLS-1$ + private static final String PROPERTY_LOCATION = "location"; //$NON-NLS-1$ + private static final String PROPERTY_RESOLUTION = "resolution"; //$NON-NLS-1$ - public void modify(Object element, String property, Object value) { - final IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection(); - final IFeatureModel model = (IFeatureModel) selection.getFirstElement(); - if (model == null) - return; - - String id = model.getFeature().getId(); - final int comboIndex = ((Integer) value).intValue(); - - if (IPDELauncherConstants.LOCATION.equalsIgnoreCase(property)) { - if (comboIndex == 0) - fFeatureLocationMap.put(id, IPDELauncherConstants.LOCATION_WORKSPACE); - if (comboIndex == 1) - fFeatureLocationMap.put(id, IPDELauncherConstants.LOCATION_EXTERNAL); - } + private Label fCounter; + private Button fAddRequiredFeaturesButton; + private Button fDefaultsButton; + private Button fSelectAllButton; + private Button fDeselectAllButton; - fViewer.refresh(model); - fTab.updateLaunchConfigurationDialog(); - } - } + private Combo fDefaultFeatureLocationCombo; + private Combo fDefaultPluginResolutionCombo; + + private HashMap fExternalFeatureMap; + private HashMap fFeatureLocationMap; + private HashMap fPluginResolutionMap; + private HashMap fWorkspaceFeatureMap; + private HashMap fFeatureVersionMap; + private HashMap fFeatureModelMap; + private ILaunchConfiguration fLaunchConfig; + private Listener fListener; + private AbstractLauncherTab fTab; + private Table fTable; + private CheckboxTableViewer fViewer; public FeatureBlock(PluginsTab pluginsTab) { Assert.isNotNull(pluginsTab); fTab = pluginsTab; } - public void createControl(Composite parent, int span, int indent) { - fListener = new Listener(); - createCheckBoxTable(parent, span - 1, indent); - createButtonContainer(parent, 10); + private Button createButton(Composite composite, String text, int style) { + Button button = new Button(composite, style); + button.setText(text); + button.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + SWTUtil.setButtonDimensionHint(button); + button.addSelectionListener(fListener); + return button; } private void createButtonContainer(Composite parent, int vOffset) { @@ -241,29 +330,18 @@ fSelectAllButton = createButton(composite, PDEUIMessages.AdvancedLauncherTab_selectAll, SWT.PUSH); fDeselectAllButton = createButton(composite, PDEUIMessages.AdvancedLauncherTab_deselectAll, SWT.PUSH); - //fAddRequiredFeaturesButton = createButton(composite, PDEUIMessages.FeatureBlock_addRequiredFeatues, SWT.PUSH); - //fAddRequiredBundlesButton = createButton(composite, PDEUIMessages.FeatureBlock_addRequiedBundles, SWT.PUSH); - fUseWrkSpcFeaturesButton = createButton(composite, PDEUIMessages.FeatureBlock_useWorkspaceFeatures, SWT.PUSH); - fUseExtrnlFeaturesButton = createButton(composite, PDEUIMessages.FeatureBlock_useExternalFeatures, SWT.PUSH); + fAddRequiredFeaturesButton = createButton(composite, PDEUIMessages.FeatureBlock_addRequiredFeatues, SWT.PUSH); fDefaultsButton = createButton(composite, PDEUIMessages.AdvancedLauncherTab_defaults, SWT.PUSH); - fFilterButton = createButton(composite, PDEUIMessages.FeatureBlock_showSelected, SWT.CHECK); - GridData filterButtonGridData = new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_END); - fFilterButton.setLayoutData(filterButtonGridData); + //fShowFilterButton = createButton(composite, PDEUIMessages.FeatureBlock_showSelected, SWT.CHECK); + //fShowFilterButton.addSelectionListener(fListener); + //GridData filterButtonGridData = new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_END); + //fShowFilterButton.setLayoutData(filterButtonGridData); fCounter = new Label(composite, SWT.NONE); fCounter.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_END)); updateCounter(); } - private Button createButton(Composite composite, String text, int style) { - Button button = new Button(composite, style); - button.setText(text); - button.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); - SWTUtil.setButtonDimensionHint(button); - button.addSelectionListener(fListener); - return button; - } - private void createCheckBoxTable(Composite parent, int span, int indent) { fViewer = CheckboxTableViewer.newCheckList(parent, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI); fTable = fViewer.getTable(); @@ -275,7 +353,7 @@ TableColumn column1 = new TableColumn(fTable, SWT.LEFT); column1.setText(PDEUIMessages.FeatureBlock_features); - column1.setWidth(300); + column1.setWidth(250); column1.addSelectionListener(fListener); column1.setData(COLUMN_ID, new Integer(0)); @@ -286,35 +364,51 @@ column2.setData(COLUMN_ID, new Integer(1)); TableColumn column3 = new TableColumn(fTable, SWT.LEFT); - column3.setText(PDEUIMessages.FeatureBlock_location); - column3.setWidth(80); + column3.setText(PDEUIMessages.FeatureBlock_featureLocation); + column3.setWidth(100); column3.addSelectionListener(fListener); column3.setData(COLUMN_ID, new Integer(2)); + TableColumn column4 = new TableColumn(fTable, SWT.LEFT); + column4.setText(PDEUIMessages.FeatureBlock_pluginResolution); + column4.setWidth(100); + column4.addSelectionListener(fListener); + column4.setData(COLUMN_ID, new Integer(3)); + fTable.setHeaderVisible(true); fViewer.setLabelProvider(new FeatureTableLabelProvider()); fViewer.setContentProvider(new PluginContentProvider()); - fViewer.setInput(getFeatures()); + fViewer.setInput(getFeatures(LOCATION_WORKSPACE)); fViewer.addCheckStateListener(new ICheckStateListener() { public void checkStateChanged(CheckStateChangedEvent event) { + String id = (String) event.getElement(); + if (event.getChecked() == false) { + fFeatureLocationMap.put(id, LOCATION_DEFAULT); + fPluginResolutionMap.put(id, LOCATION_DEFAULT); + IFeatureModel model = (IFeatureModel) fWorkspaceFeatureMap.get(id); + if (model == null) { + model = (IFeatureModel) fExternalFeatureMap.get(id); + } + fFeatureModelMap.put(id, model); + fFeatureVersionMap.put(id, model.getFeature().getVersion()); + } + fViewer.refresh(id, true); fTab.updateLaunchConfigurationDialog(); } }); - fListener.handleColumn(column3); - - String[] items = new String[] {PDEUIMessages.FeatureBlock_workspace, PDEUIMessages.FeatureBlock_external}; - fViewer.setCellEditors(new CellEditor[] {null, null, new ComboBoxCellEditor(fTable, items)}); - fViewer.setColumnProperties(new String[] {null, null, IPDELauncherConstants.LOCATION}); + String[] items = new String[] {PDEUIMessages.FeatureBlock_default, PDEUIMessages.FeatureBlock_workspaceBefore, PDEUIMessages.FeatureBlock_externalBefore}; + fViewer.setCellEditors(new CellEditor[] {null, null, new ComboBoxCellEditor(fTable, items), new ComboBoxCellEditor(fTable, items)}); + fViewer.setColumnProperties(new String[] {null, null, PROPERTY_LOCATION, PROPERTY_RESOLUTION}); fViewer.setCellModifier(new LocationCellModifier()); fViewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { - final ISelection selection = event.getSelection(); + ISelection selection = event.getSelection(); if (selection == null || !(selection instanceof IStructuredSelection)) { return; } @@ -322,33 +416,124 @@ } }); + TableViewerColumn tvc = new TableViewerColumn(fViewer, column3); + tvc.setLabelProvider(new CellLabelProvider() { + + public void update(ViewerCell cell) { + String id = (String) cell.getElement(); + Display display = fTable.getDisplay(); + Color gray = display.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW); + Color white = display.getSystemColor(SWT.COLOR_WHITE); + if (fWorkspaceFeatureMap.containsKey(id) && fExternalFeatureMap.containsKey(id) && fViewer.getChecked(id)) { + cell.setBackground(white); + } else { + cell.setBackground(gray); + } + FeatureTableLabelProvider provider = (FeatureTableLabelProvider) fViewer.getLabelProvider(); + cell.setText(provider.getColumnText(id, COLUMN_FEATURE_LOCATION)); + } + }); + } + + public void createControl(Composite parent, int span, int indent) { + fListener = new Listener(); + + Label label = SWTFactory.createLabel(parent, PDEUIMessages.FeatureBlock_defaultFeatureLocation, 1); + GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); + gd.horizontalIndent = indent; + label.setLayoutData(gd); + fDefaultFeatureLocationCombo = SWTFactory.createCombo(parent, SWT.READ_ONLY | SWT.BORDER, 1, GridData.HORIZONTAL_ALIGN_BEGINNING, new String[] {PDEUIMessages.FeatureBlock_workspaceBefore, PDEUIMessages.FeatureBlock_externalBefore}); + + label = SWTFactory.createLabel(parent, PDEUIMessages.FeatureBlock_defaultPluginResolution, 1); + fDefaultPluginResolutionCombo = SWTFactory.createCombo(parent, SWT.READ_ONLY | SWT.BORDER, 1, GridData.HORIZONTAL_ALIGN_BEGINNING, new String[] {PDEUIMessages.FeatureBlock_workspaceBefore, PDEUIMessages.FeatureBlock_externalBefore}); + + fDefaultFeatureLocationCombo.addSelectionListener(fListener); + fDefaultPluginResolutionCombo.addSelectionListener(fListener); + createCheckBoxTable(parent, span - 1, indent); + createButtonContainer(parent, 10); } - private Object getFeatures() { + public void dispose() { + PDEPlugin.getDefault().getLabelProvider().disconnect(this); + } + + private Object getFeatures(String defaultLocation) { FeatureModelManager fmm = new FeatureModelManager(); + fWorkspaceFeatureMap = new HashMap(); fExternalFeatureMap = new HashMap(); fFeatureLocationMap = new HashMap(); - ArrayList features = new ArrayList(); + fPluginResolutionMap = new HashMap(); + fFeatureVersionMap = new HashMap(); + fFeatureModelMap = new HashMap(); + IFeatureModel[] workspaceModels = fmm.getWorkspaceModels(); for (int i = 0; i < workspaceModels.length; i++) { String id = workspaceModels[i].getFeature().getId(); fWorkspaceFeatureMap.put(id, workspaceModels[i]); - fFeatureLocationMap.put(id, IPDELauncherConstants.LOCATION_WORKSPACE); - features.add(workspaceModels[i]); - } - - IFeatureModel[] externalModels = fmm.getModels(); + fFeatureLocationMap.put(id, LOCATION_DEFAULT); + fPluginResolutionMap.put(id, LOCATION_DEFAULT); + fFeatureVersionMap.put(id, workspaceModels[i].getFeature().getVersion()); + fFeatureModelMap.put(id, workspaceModels[i]); + } + fmm.shutdown(); + + ExternalFeatureModelManager efmm = new ExternalFeatureModelManager(); + efmm.startup(); + IFeatureModel[] externalModels = efmm.getModels(); for (int i = 0; i < externalModels.length; i++) { String id = externalModels[i].getFeature().getId(); fExternalFeatureMap.put(id, externalModels[i]); - if (!fWorkspaceFeatureMap.containsKey(id)) { - features.add(externalModels[i]); - fFeatureLocationMap.put(id, IPDELauncherConstants.LOCATION_EXTERNAL); + if (LOCATION_EXTERNAL.equalsIgnoreCase(defaultLocation) || (LOCATION_WORKSPACE.equalsIgnoreCase(defaultLocation) && !fWorkspaceFeatureMap.containsKey(id))) { + fFeatureLocationMap.put(id, LOCATION_DEFAULT); + fPluginResolutionMap.put(id, LOCATION_DEFAULT); + fFeatureVersionMap.put(id, externalModels[i].getFeature().getVersion()); + fFeatureModelMap.put(id, externalModels[i]); } } + efmm.shutdown(); + return fFeatureModelMap.keySet().toArray(new String[fFeatureModelMap.size()]); + } - return features.toArray(new IFeatureModel[features.size()]); + private String getLocationConstant(String value) { + if (PDEUIMessages.FeatureBlock_workspaceBefore.equalsIgnoreCase(value)) { + return LOCATION_WORKSPACE; + } else if (PDEUIMessages.FeatureBlock_externalBefore.equalsIgnoreCase(value)) { + return LOCATION_EXTERNAL; + } + return value; + } + + private String getLocationText(String location) { + if (LOCATION_DEFAULT.equalsIgnoreCase(location)) { + return PDEUIMessages.FeatureBlock_default; + } else if (LOCATION_WORKSPACE.equalsIgnoreCase(location)) { + return PDEUIMessages.FeatureBlock_workspaceBefore; + } else if (LOCATION_EXTERNAL.equalsIgnoreCase(location)) { + return PDEUIMessages.FeatureBlock_externalBefore; + } + return ""; //$NON-NLS-1$ + } + + private IFeatureModel getFeatureModel(String id) { + String version = (String) fFeatureVersionMap.get(id); + Version featureVersion = Version.parseVersion(version); + IFeatureModel model = (IFeatureModel) fExternalFeatureMap.get(id); + Version modelVersion = Version.parseVersion(model.getFeature().getVersion()); + if (VersionUtil.isEquivalentTo(featureVersion, modelVersion)) { + return model; + } + + model = (IFeatureModel) fWorkspaceFeatureMap.get(id); + modelVersion = Version.parseVersion(model.getFeature().getVersion()); + if (VersionUtil.isEquivalentTo(featureVersion, modelVersion)) { + return model; + } + return null; + } + + public void initialize() throws CoreException { + initializeFrom(fLaunchConfig); } public void initializeFrom(ILaunchConfiguration config) throws CoreException { @@ -358,22 +543,18 @@ } fLaunchConfig = config; - fViewer.setInput(getFeatures()); - HashMap featureMap = BundleLauncherHelper.getFeatureLocationMap(config); - for (Iterator iterator = featureMap.keySet().iterator(); iterator.hasNext();) { - String id = (String) iterator.next(); - String location = (String) featureMap.get(id); - fFeatureLocationMap.put(id, location); - Object model = null; - if (IPDELauncherConstants.LOCATION_WORKSPACE.equalsIgnoreCase(location)) { - model = fWorkspaceFeatureMap.get(id); - } else if (IPDELauncherConstants.LOCATION_EXTERNAL.equalsIgnoreCase(location)) { - model = fExternalFeatureMap.get(id); - } - if (model != null) { - fViewer.setChecked(model, true); - fViewer.refresh(model, true); - } + String defaultLocation = config.getAttribute(IPDELauncherConstants.FEATURE_DEFAULT_LOCATION, LOCATION_WORKSPACE); + fDefaultFeatureLocationCombo.setText(getLocationText(defaultLocation)); + String pluginResolution = config.getAttribute(IPDELauncherConstants.FEATURE_PLUGIN_RESOLUTION, LOCATION_WORKSPACE); + fDefaultPluginResolutionCombo.setText(getLocationText(pluginResolution)); + fViewer.setInput(getFeatures(defaultLocation)); + + ArrayList selectedFeatureList = BundleLauncherHelper.getFeatureMaps(config, fFeatureVersionMap, fFeatureLocationMap, fPluginResolutionMap); + + for (int index = 0; index < selectedFeatureList.size(); index++) { + String id = (String) selectedFeatureList.get(index); + fFeatureModelMap.put(id, getFeatureModel(id)); + fViewer.setChecked(id, true); } // If the workspace plug-in state has changed (project closed, etc.) the launch config needs to be updated without making the tab dirty @@ -384,52 +565,59 @@ updateCounter(); fTab.updateLaunchConfigurationDialog(); - } - - private void updateCounter() { - if (fCounter != null) { - int checked = fViewer.getCheckedElements().length; - int total = fFeatureLocationMap.keySet().size(); - fCounter.setText(NLS.bind(PDEUIMessages.AbstractPluginBlock_counter, new Integer(checked), new Integer(total))); - } + PDEPreferencesManager prefs = new PDEPreferencesManager(IPDEUIConstants.PLUGIN_ID); + int index = prefs.getInt(IPreferenceConstants.FEATURE_SORT_COLUMN); + TableColumn column = fTable.getColumn(index == 0 ? COLUMN_FEATURE_LOCATION : index - 1); + fListener.handleColumn(column, prefs.getInt(IPreferenceConstants.FEATURE_SORT_ORDER)); + fViewer.refresh(true); } public void performApply(ILaunchConfigurationWorkingCopy config) { - //TODO update these when real buttons are added to UI - config.setAttribute(IPDELauncherConstants.INCLUDE_OPTIONAL, true); - config.setAttribute(IPDELauncherConstants.AUTOMATIC_ADD, true); - config.setAttribute(IPDELauncherConstants.AUTOMATIC_VALIDATE, false); config.setAttribute(IPDELauncherConstants.SHOW_SELECTED_ONLY, false); savePluginState(config); + saveSortOrder(); updateCounter(); } private void savePluginState(ILaunchConfigurationWorkingCopy config) { StringBuffer featuresEntry = new StringBuffer(); if (fViewer.getCheckedElements() != null && fViewer.getCheckedElements().length > 0) { - Object[] featureModels = fViewer.getCheckedElements(); - for (int i = 0; i < featureModels.length; i++) { - IFeature feature = ((IFeatureModel) featureModels[i]).getFeature(); - String location = (String) fFeatureLocationMap.get(feature.getId()); - String value = BundleLauncherHelper.writeFeatureEntry(feature.getId(), feature.getVersion(), location); + Object[] selectedFeatureModels = fViewer.getCheckedElements(); + Arrays.sort(selectedFeatureModels); // So that Tab is not marked dirty due to Sorting changes + for (int i = 0; i < selectedFeatureModels.length; i++) { + String id = (String) selectedFeatureModels[i]; + String location = (String) fFeatureLocationMap.get(id); + String resolution = (String) fPluginResolutionMap.get(id); + String version = (String) fFeatureVersionMap.get(id); + String value = BundleLauncherHelper.writeFeatureEntry(id, version, location, resolution); featuresEntry.append(value); } } config.setAttribute(IPDELauncherConstants.SELECTED_FEATURES, featuresEntry.length() == 0 ? (String) null : featuresEntry.toString()); + config.setAttribute(IPDELauncherConstants.FEATURE_DEFAULT_LOCATION, getLocationConstant(fDefaultFeatureLocationCombo.getText())); + config.setAttribute(IPDELauncherConstants.FEATURE_PLUGIN_RESOLUTION, getLocationConstant(fDefaultPluginResolutionCombo.getText())); + } - public void setDefaults(ILaunchConfigurationWorkingCopy config) { - config.setAttribute(IPDELauncherConstants.INCLUDE_OPTIONAL, true); - config.setAttribute(IPDELauncherConstants.AUTOMATIC_ADD, true); - config.setAttribute(IPDELauncherConstants.AUTOMATIC_VALIDATE, false); - config.setAttribute(IPDELauncherConstants.SHOW_SELECTED_ONLY, false); + private void saveSortOrder() { + PDEPreferencesManager prefs = new PDEPreferencesManager(IPDEUIConstants.PLUGIN_ID); + TableColumn column = fTable.getSortColumn(); + int index = column == null ? 0 : ((Integer) fTable.getSortColumn().getData(COLUMN_ID)).intValue(); + prefs.setValue(IPreferenceConstants.FEATURE_SORT_COLUMN, index + 1); + int sortOrder = column == null ? 0 : fTable.getSortDirection(); + prefs.setValue(IPreferenceConstants.FEATURE_SORT_ORDER, sortOrder); + prefs.savePluginPreferences(); } - public void dispose() { - PDEPlugin.getDefault().getLabelProvider().disconnect(this); + public void setDefaults(ILaunchConfigurationWorkingCopy config) { + config.setAttribute(IPDELauncherConstants.SHOW_SELECTED_ONLY, false); } - public void initialize() throws CoreException { - initializeFrom(fLaunchConfig); + private void updateCounter() { + if (fCounter != null) { + int checked = fViewer.getCheckedElements().length; + int total = fFeatureLocationMap.keySet().size(); + fCounter.setText(NLS.bind(PDEUIMessages.AbstractPluginBlock_counter, new Integer(checked), new Integer(total))); + } } }