diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/core/plugin/IPluginImport.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/core/plugin/IPluginImport.java index 157788ab70d..8af5fc065a8 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/core/plugin/IPluginImport.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/core/plugin/IPluginImport.java @@ -34,6 +34,11 @@ public interface IPluginImport extends IPluginObject, IPluginReference { */ String P_OPTIONAL = "optional"; //$NON-NLS-1$ + /** + * @since 3.21 + */ + String P_FILTER = "filter"; //$NON-NLS-1$ + /** * Tests whether the imported plug-in is reexported for * plug-ins that will use this plug-in. @@ -70,4 +75,17 @@ public interface IPluginImport extends IPluginObject, IPluginReference { */ void setOptional(boolean value) throws CoreException; + /** + * @since 3.21 + */ + void setFilter(String filter) throws CoreException; + + /** + * Returns the filter string for this plugin reference. + * + * @return the filter string, or null if not set + * @since 3.21 + */ + String getFilter(); + } diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/plugin/PluginImport.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/plugin/PluginImport.java index 1911c6444dd..ced4b605ed8 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/plugin/PluginImport.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/plugin/PluginImport.java @@ -46,6 +46,7 @@ public class PluginImport extends IdentifiablePluginObject implements IPluginImp private boolean reexported = false; private boolean optional = false; private String version; + private String filter; public PluginImport() { } @@ -74,6 +75,11 @@ public String getVersion() { return version; } + @Override + public String getFilter() { + return filter; + } + @Override public boolean isReexported() { return reexported; @@ -203,6 +209,15 @@ public void setVersion(String version) throws CoreException { firePropertyChanged(P_VERSION, oldValue, version); } + @Override + public void setFilter(String filter) throws CoreException { + ensureModelEditable(); + String oldValue = this.filter; + this.filter = filter; + firePropertyChanged(P_FILTER, oldValue, filter); + + } + @Override public void restoreProperty(String name, Object oldValue, Object newValue) throws CoreException { if (name.equals(P_MATCH)) { @@ -312,4 +327,6 @@ public void writeDelimeter(PrintWriter writer) { writer.print(' '); } + + } diff --git a/ui/org.eclipse.pde.core/text/org/eclipse/pde/internal/core/text/plugin/PluginImportNode.java b/ui/org.eclipse.pde.core/text/org/eclipse/pde/internal/core/text/plugin/PluginImportNode.java index e9e1c574676..233aefa2c8f 100644 --- a/ui/org.eclipse.pde.core/text/org/eclipse/pde/internal/core/text/plugin/PluginImportNode.java +++ b/ui/org.eclipse.pde.core/text/org/eclipse/pde/internal/core/text/plugin/PluginImportNode.java @@ -21,6 +21,17 @@ public class PluginImportNode extends PluginObjectNode implements IPluginImport private static final long serialVersionUID = 1L; + @Override + public void setFilter(String filter) { + setXMLAttribute(P_FILTER, filter); + + } + + @Override + public String getFilter() { + return getXMLAttributeValue(P_FILTER); + } + public PluginImportNode(String id) { super(); String name = "plugin"; //$NON-NLS-1$ diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java index a2f51440d1d..ff5cf72e6de 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java @@ -247,6 +247,7 @@ public class PDEUIMessages extends NLS { public static String ContainerRenameParticipant_renameBundleId; public static String ControlValidationUtility_errorMsgFilterInvalidSyntax; + public static String ControlValidationUtility_errorMsgFeatureFilterInvalidSyntax; public static String ControlValidationUtility_errorMsgKeyNotFound; public static String ControlValidationUtility_errorMsgNotOnClasspath; public static String ControlValidationUtility_errorMsgPluginUnresolved; @@ -977,6 +978,7 @@ public class PDEUIMessages extends NLS { public static String ManifestEditor_MatchSection_equivalent; public static String ManifestEditor_MatchSection_compatible; public static String ManifestEditor_MatchSection_greater; + public static String ManifestEditor_MatchSection_filter; public static String ManifestEditor_PluginSpecSection_title; public static String ManifestEditor_PluginSpecSection_desc; diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/plugin/MatchSection.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/plugin/MatchSection.java index 90c118e9f59..dc9617f1bf2 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/plugin/MatchSection.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/plugin/MatchSection.java @@ -25,6 +25,7 @@ import org.eclipse.pde.core.plugin.IMatchRules; import org.eclipse.pde.core.plugin.IPluginImport; import org.eclipse.pde.core.plugin.IPluginReference; +import org.eclipse.pde.internal.core.ifeature.IFeatureImport; import org.eclipse.pde.internal.core.plugin.ImportObject; import org.eclipse.pde.internal.ui.PDEPlugin; import org.eclipse.pde.internal.ui.PDEUIMessages; @@ -32,6 +33,8 @@ import org.eclipse.pde.internal.ui.editor.FormLayoutFactory; import org.eclipse.pde.internal.ui.editor.PDEFormPage; import org.eclipse.pde.internal.ui.editor.PDESection; +import org.eclipse.pde.internal.ui.editor.validation.ControlValidationUtility; +import org.eclipse.pde.internal.ui.editor.validation.TextValidator; import org.eclipse.pde.internal.ui.parts.ComboPart; import org.eclipse.pde.internal.ui.parts.FormEntry; import org.eclipse.swt.SWT; @@ -44,13 +47,18 @@ import org.eclipse.ui.forms.IPartSelectionListener; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.Section; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; public class MatchSection extends PDESection implements IPartSelectionListener { + private Button fReexportButton; private Button fOptionalButton; private FormEntry fVersionText; + private FormEntry fFilterText; + private TextValidator fFilterEntryValidator; private ComboPart fMatchCombo; protected IPluginReference fCurrentImport; @@ -134,6 +142,32 @@ public void textDirty(FormEntry text) { })); toolkit.paintBordersFor(container); initialize(); + + fFilterText = new FormEntry(container, toolkit, PDEUIMessages.ManifestEditor_MatchSection_filter, null, false); + fFilterText.setFormEntryListener( + new FormEntryAdapter(this, getPage().getEditor().getEditorSite().getActionBars()) { + @Override + public void textValueChanged(FormEntry text) { + applyFilter(text.getValue()); + } + + @Override + public void textDirty(FormEntry text) { + if (fBlockChanges) { + return; + } + markDirty(); + fBlockChanges = true; + resetMatchCombo(fCurrentImport); + fBlockChanges = false; + } + }); + fFilterEntryValidator = new TextValidator(getManagedForm(), fFilterText.getText(), getProject(), true) { + @Override + protected boolean validateControl() { + return validateFilter(); + } + }; update((IPluginReference) null); section.setClient(container); @@ -143,6 +177,16 @@ public void textDirty(FormEntry text) { section.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING)); } + private boolean validateFilter() { + // No validation required for an optional field + if (fFilterText.getText().getText().length() == 0) { + return true; + } + // Value must match the current environment and contain valid syntax + return ControlValidationUtility.validateFilterField(fFilterText.getText().getText(), + fFilterEntryValidator); + } + private void createReexportButton(FormToolkit toolkit, Composite container) { fReexportButton = toolkit.createButton(container, PDEUIMessages.ManifestEditor_MatchSection_reexport, SWT.CHECK); fReexportButton.addSelectionListener(widgetSelectedAdapter(e -> { @@ -200,6 +244,22 @@ private void applyMatch(int match) { } } + private void applyFilter(String filter) { + try { + if (fCurrentImport == null) + return; + if (filter == null || filter.isEmpty()) + ((IFeatureImport) fCurrentImport).setFilter(null); + else { + FrameworkUtil.createFilter(filter); + ((IFeatureImport) fCurrentImport).setFilter(filter); + } + } catch (InvalidSyntaxException e) { + } catch (CoreException e) { + PDEPlugin.logException(e); + } + } + private int getMatch() { return fMatchCombo.getSelectionIndex(); } @@ -272,8 +332,11 @@ protected void update(IPluginReference iimport) { } fVersionText.setValue(null, true); fVersionText.setEditable(false); + fMatchCombo.getControl().setEnabled(false); fMatchCombo.setText(""); //$NON-NLS-1$ + fFilterText.setValue(null, false); + fFilterText.setEditable(false); fCurrentImport = null; fBlockChanges = false; return; @@ -292,7 +355,10 @@ protected void update(IPluginReference iimport) { } fVersionText.setEditable(isEditable()); fVersionText.setValue(fCurrentImport.getVersion()); + resetMatchCombo(fCurrentImport); + fFilterText.setEditable(isEditable()); + fFilterText.setValue(((IFeatureImport) fCurrentImport).getFilter()); fBlockChanges = false; } } diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/validation/ControlValidationUtility.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/validation/ControlValidationUtility.java index 74dbcc721b4..57b39f9a0de 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/validation/ControlValidationUtility.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/editor/validation/ControlValidationUtility.java @@ -95,6 +95,19 @@ public static boolean validatePlatformFilterField(String value, IValidatorMessag return true; } + public static boolean validateFilterField(String value, IValidatorMessageHandler validator) { + // Check to see if the platform filter syntax is valid + try { + PDECore.getDefault().getBundleContext().createFilter(value); + } catch (InvalidSyntaxException ise) { + validator.addMessage(PDEUIMessages.ControlValidationUtility_errorMsgFeatureFilterInvalidSyntax, + IMessageProvider.ERROR); + return false; + } + + return true; + } + public static boolean validateActivatorField(String value, IValidatorMessageHandler validator, IProject project) { // Check the compiler flag and translate it into a message type diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties index ae99f17e635..c8c874d94db 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties @@ -388,6 +388,7 @@ ManifestEditor_MatchSection_perfect = Perfect ManifestEditor_MatchSection_equivalent = Equivalent ManifestEditor_MatchSection_compatible = Compatible ManifestEditor_MatchSection_greater = Greater or Equal +ManifestEditor_MatchSection_filter = Filter: ManifestEditor_PluginSpecSection_title = General Information ManifestEditor_PluginSpecSection_desc = This section describes general information about this plug-in. @@ -2523,6 +2524,7 @@ ControlValidationUtility_errorMsgValueMustBeSpecified=A value must be specified ControlValidationUtility_errorMsgValueNotExternalized=The specified value is not externalized ControlValidationUtility_errorMsgKeyNotFound=The specified key is not present in the plug-in's properties file ControlValidationUtility_errorMsgFilterInvalidSyntax=The specified platform filter contains invalid syntax +ControlValidationUtility_errorMsgFeatureFilterInvalidSyntax=The specified feature filter contains invalid syntax PackageFinder_taskName=Searching class files for package references UpdateSingleton_dir_label=Update ''{0}'' to 'singleton' directive true