diff --git a/org.eclipse.m2e.pde.ui/src/org/eclipse/m2e/pde/ui/editor/ClipboardParser.java b/org.eclipse.m2e.pde.ui/src/org/eclipse/m2e/pde/ui/editor/ClipboardParser.java index 6c73b43a31..3830f38258 100644 --- a/org.eclipse.m2e.pde.ui/src/org/eclipse/m2e/pde/ui/editor/ClipboardParser.java +++ b/org.eclipse.m2e.pde.ui/src/org/eclipse/m2e/pde/ui/editor/ClipboardParser.java @@ -20,8 +20,8 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; +import org.apache.maven.artifact.Artifact; import org.eclipse.m2e.pde.MavenTargetDependency; -import org.eclipse.m2e.pde.MavenTargetLocation; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -46,16 +46,11 @@ public ClipboardParser(String text) { for (int i = 0; i < dependencies.getLength(); i++) { Node item = dependencies.item(i); if (item instanceof Element) { - Element element = (Element) item; - String groupId = getTextFor("groupId", element, ""); - String artifactId = getTextFor("artifactId", element, ""); - String version = getTextFor("version", element, ""); - String classifier = getTextFor("classifier", element, ""); - String type = getTextFor("type", element, MavenTargetLocation.DEFAULT_DEPENDENCY_SCOPE); - this.dependencies - .add(new MavenTargetDependency(groupId, artifactId, version, type, classifier)); + parseElement((Element) item); } - + } + if (this.dependencies.isEmpty()) { + parseElement(doc.getDocumentElement()); } } catch (Exception e) { // we can't use the clipboard content then... @@ -64,6 +59,16 @@ public ClipboardParser(String text) { } } + private void parseElement(Element element) { + String groupId = getTextFor("groupId", element, ""); + String artifactId = getTextFor("artifactId", element, ""); + String version = getTextFor("version", element, ""); + String classifier = getTextFor("classifier", element, ""); + String type = getTextFor("type", element, Artifact.SCOPE_COMPILE); + this.dependencies + .add(new MavenTargetDependency(groupId, artifactId, version, type, classifier)); + } + private String getTextFor(String element, Element doc, String defaultValue) { NodeList nl = doc.getElementsByTagName(element); Node item = nl.item(0); diff --git a/org.eclipse.m2e.pde.ui/src/org/eclipse/m2e/pde/ui/editor/MavenTargetLocationWizard.java b/org.eclipse.m2e.pde.ui/src/org/eclipse/m2e/pde/ui/editor/MavenTargetLocationWizard.java index 8e71dba796..77a2f81ce1 100644 --- a/org.eclipse.m2e.pde.ui/src/org/eclipse/m2e/pde/ui/editor/MavenTargetLocationWizard.java +++ b/org.eclipse.m2e.pde.ui/src/org/eclipse/m2e/pde/ui/editor/MavenTargetLocationWizard.java @@ -15,6 +15,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; import java.util.Objects; @@ -59,8 +60,11 @@ public class MavenTargetLocationWizard extends Wizard implements ITargetLocationWizard { + private static final List MAVEN_SCOPES = List.of(Artifact.SCOPE_COMPILE, Artifact.SCOPE_PROVIDED, + Artifact.SCOPE_RUNTIME, Artifact.SCOPE_TEST, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_IMPORT); + private MavenTargetLocation targetLocation; - private CCombo scope; + private Button[] scopes; private ComboViewer metadata; private ComboViewer include; private ITargetDefinition targetDefinition; @@ -92,7 +96,6 @@ public MavenTargetLocationWizard(MavenTargetLocation targetLocation) { targetLocation == null ? Messages.MavenTargetLocationWizard_1 : Messages.MavenTargetLocationWizard_2) { private Link editInstructionsButton; - private Label scopeDescriptionLabel; private Label includeLabel; private Label scopeLabel; @@ -133,7 +136,7 @@ public void modifyText(ModifyEvent e) { createIncludeCombo(composite); scopeLabel = new Label(composite, SWT.NONE); scopeLabel.setText(Messages.MavenTargetLocationWizard_10); - createScopeCombo(composite); + createScopes(composite); includeSource = createCheckBox(composite, Messages.MavenTargetLocationWizard_8); createFeature = createCheckBox(composite, Messages.MavenTargetLocationWizard_13); createFeature.addSelectionListener(new SelectionListener() { @@ -149,11 +152,12 @@ public void widgetDefaultSelected(SelectionEvent e) { } }); if (targetLocation != null) { - String dependencyScope = targetLocation.getDependencyScope(); - if (dependencyScope == null || dependencyScope.isBlank()) { - dependencyScope = Artifact.SCOPE_COMPILE; + Collection dependencyScopes = targetLocation.getDependencyScopes(); + for (int i = 0; i < scopes.length; i++) { + if (dependencyScopes.contains(MAVEN_SCOPES.get(i))) { + scopes[i].setSelection(true); + } } - scope.setText(dependencyScope); metadata.setSelection(new StructuredSelection(targetLocation.getMetadataMode())); include.setSelection(new StructuredSelection(targetLocation.getDependencyDepth())); bndInstructions = targetLocation.getInstructions(null); @@ -204,26 +208,30 @@ public String getText(Object element) { include.addSelectionChangedListener(e -> updateUI()); } - private void createScopeCombo(Composite parent) { + private void createScopes(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); - GridLayout layout = new GridLayout(2, false); - layout.horizontalSpacing = 20; + GridLayout layout = new GridLayout(MAVEN_SCOPES.size() + 1, false); + layout.horizontalSpacing = 10; layout.marginWidth = 0; layout.marginHeight = 0; composite.setLayout(layout); - scope = combo(new CCombo(composite, SWT.READ_ONLY | SWT.BORDER | SWT.FLAT)); - scopeDescriptionLabel = new Label(composite, SWT.NONE); - scopeDescriptionLabel.setText(Messages.MavenTargetLocationWizard_15); - scope.add(Artifact.SCOPE_COMPILE); - scope.add(Artifact.SCOPE_PROVIDED); - scope.add(Artifact.SCOPE_TEST); - scope.addModifyListener(new ModifyListener() { + scopes = new Button[MAVEN_SCOPES.size()]; + for (int i = 0; i < scopes.length; i++) { + scopes[i] = new Button(composite, SWT.CHECK); + scopes[i].setText(MAVEN_SCOPES.get(i)); + scopes[i].addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + updateUI(); + } - @Override - public void modifyText(ModifyEvent e) { - updateUI(); - } - }); + @Override + public void widgetDefaultSelected(SelectionEvent e) { + + } + }); + } } private void createMetadataCombo(Composite parent) { @@ -274,13 +282,15 @@ private void updateUI() { editInstructionsButton.setVisible( metadata.getStructuredSelection().getFirstElement() == MissingMetadataMode.GENERATE); if (include.getStructuredSelection().getFirstElement() == DependencyDepth.NONE) { - scopeDescriptionLabel.setVisible(false); - scope.setEnabled(false); + for (Button button : scopes) { + button.setEnabled(false); + } scopeLabel.setEnabled(false); } else { scopeLabel.setEnabled(true); - scope.setEnabled(true); - scopeDescriptionLabel.setVisible(true); + for (Button button : scopes) { + button.setEnabled(true); + } } getContainer().updateButtons(); } @@ -384,10 +394,16 @@ public boolean performFinish() { } @SuppressWarnings("restriction") IFeature f = createFeature ? featureModel.getFeature() : null; + Collection selectedScopes = new LinkedHashSet<>(); + for (int i = 0; i < scopes.length; i++) { + if (scopes[i].getSelection()) { + selectedScopes.add(MAVEN_SCOPES.get(i)); + } + } DependencyDepth depth = (DependencyDepth) include.getStructuredSelection().getFirstElement(); MavenTargetLocation location = new MavenTargetLocation(locationLabel.getText(), dependencyEditor.getRoots(), repositoryList, (MissingMetadataMode) metadata.getStructuredSelection().getFirstElement(), depth, - scope.getText(), includeSource.getSelection(), list, excludes, f); + selectedScopes, includeSource.getSelection(), list, excludes, f); if (iscreate) { targetLocation = location; } else { diff --git a/org.eclipse.m2e.pde.ui/src/org/eclipse/m2e/pde/ui/editor/messages.properties b/org.eclipse.m2e.pde.ui/src/org/eclipse/m2e/pde/ui/editor/messages.properties index 7565d2ef81..53bcf9b122 100644 --- a/org.eclipse.m2e.pde.ui/src/org/eclipse/m2e/pde/ui/editor/messages.properties +++ b/org.eclipse.m2e.pde.ui/src/org/eclipse/m2e/pde/ui/editor/messages.properties @@ -17,11 +17,10 @@ MavenTargetLocationWizard_8=Include Artifact Sources MavenTargetLocationWizard_12=Artifacts are resolved against the workspace maven configuration,\nyou can configure additional artifact repositories if required.\n MavenTargetLocationWizard_14=Label (optional) MavenTargetLocationWizard_9=Missing OSGi-Manifest -MavenTargetLocationWizard_10=Dependencies scope +MavenTargetLocationWizard_10=Dependencies scopes MavenTargetLocationWizard_17=Dependencies depth MavenTargetRepositoryEditor_1=New Repository... ClipboardParser_1=Clipboard content was ignored: {0} -MavenTargetLocationWizard_15=Specify the scope for included dependencies MavenTargetLocationWizard_16=Specify the depth for included dependencies MavenTargetLocationWizard_20=Edit instructions MavenTargetLocationWizard_21=Edit the default instructions used in case of necessary manifest generation diff --git a/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/DependencyNodeGenerator.java b/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/DependencyNodeGenerator.java index 75d5a1785a..4484fab382 100644 --- a/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/DependencyNodeGenerator.java +++ b/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/DependencyNodeGenerator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2021 Christoph Läubrich + * Copyright (c) 2018, 2022 Christoph Läubrich * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at @@ -12,6 +12,7 @@ *******************************************************************************/ package org.eclipse.m2e.pde; +import java.util.Collection; import java.util.List; import org.apache.maven.RepositoryUtils; @@ -37,17 +38,18 @@ final class DependencyNodeGenerator implements ICallable repositories; private final MavenTargetDependency root; - private String dependencyScope; + private Collection dependencyScopes; private MavenTargetLocation parent; private DependencyDepth dependencyDepth; DependencyNodeGenerator(MavenTargetDependency root, Artifact artifact, DependencyDepth dependencyDepth, - String dependencyScope, List repositories, MavenTargetLocation parent) { + Collection dependencyScopes, List repositories, + MavenTargetLocation parent) { this.artifact = artifact; this.dependencyDepth = dependencyDepth; this.repositories = repositories; this.root = root; - this.dependencyScope = dependencyScope; + this.dependencyScopes = dependencyScopes; this.parent = parent; } @@ -68,7 +70,7 @@ public PreorderNodeListGenerator call(IMavenExecutionContext context, IProgressM DependencyRequest dependencyRequest = new DependencyRequest(); dependencyRequest.setRoot(node); dependencyRequest - .setFilter(new MavenTargetDependencyFilter(dependencyDepth, dependencyScope)); + .setFilter(new MavenTargetDependencyFilter(dependencyDepth, dependencyScopes)); repoSystem.resolveDependencies(context.getRepositorySession(), dependencyRequest); PreorderNodeListGenerator nlg = new PreorderNodeListGenerator(); node.accept(nlg); diff --git a/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/MavenTargetDependencyFilter.java b/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/MavenTargetDependencyFilter.java index 464c1e640e..309bbd78e0 100644 --- a/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/MavenTargetDependencyFilter.java +++ b/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/MavenTargetDependencyFilter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021 Christoph Läubrich + * Copyright (c) 2022 Christoph Läubrich * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at @@ -18,6 +18,7 @@ import static org.apache.maven.artifact.Artifact.SCOPE_SYSTEM; import static org.apache.maven.artifact.Artifact.SCOPE_TEST; +import java.util.Collection; import java.util.List; import org.eclipse.aether.graph.Dependency; @@ -27,12 +28,12 @@ public class MavenTargetDependencyFilter implements DependencyFilter { private static final String[] VALID_EXTENSIONS = { "jar", "pom" }; - private String locationScope; + private Collection locationScopes; private DependencyDepth dependencyDepth; - public MavenTargetDependencyFilter(DependencyDepth dependencyDepth, String scope) { + public MavenTargetDependencyFilter(DependencyDepth dependencyDepth, Collection dependencyScopes) { this.dependencyDepth = dependencyDepth; - this.locationScope = scope; + this.locationScopes = dependencyScopes; } @Override @@ -55,18 +56,27 @@ private boolean isValidScope(Dependency dependency) { if (dependecyScope == null || dependecyScope.isBlank()) { return true; } - if (locationScope == null || locationScope.isBlank() || SCOPE_COMPILE.equalsIgnoreCase(locationScope)) { + if (locationScopes.isEmpty()) { return SCOPE_COMPILE.equalsIgnoreCase(dependecyScope); } - if (SCOPE_PROVIDED.equalsIgnoreCase(locationScope)) { - return SCOPE_PROVIDED.equalsIgnoreCase(dependecyScope) || SCOPE_COMPILE.equalsIgnoreCase(dependecyScope) - || SCOPE_SYSTEM.equalsIgnoreCase(dependecyScope) || SCOPE_RUNTIME.equalsIgnoreCase(dependecyScope); - } - if (SCOPE_TEST.equalsIgnoreCase(locationScope)) { - return SCOPE_TEST.equalsIgnoreCase(dependecyScope) || SCOPE_COMPILE.equalsIgnoreCase(dependecyScope) - || SCOPE_PROVIDED.equalsIgnoreCase(dependecyScope) || SCOPE_SYSTEM.equalsIgnoreCase(dependecyScope) - || SCOPE_RUNTIME.equalsIgnoreCase(dependecyScope); + for (String locationScope : locationScopes) { + if (dependecyScope.equalsIgnoreCase(locationScope)) { + return true; + } } return false; } + + static final Collection expandScope(String scope) { + if (scope == null || scope.isBlank() || SCOPE_COMPILE.equalsIgnoreCase(scope)) { + return List.of(SCOPE_COMPILE); + } + if (SCOPE_PROVIDED.equalsIgnoreCase(scope)) { + return List.of(SCOPE_PROVIDED, SCOPE_COMPILE, SCOPE_SYSTEM, SCOPE_RUNTIME); + } + if (SCOPE_TEST.equalsIgnoreCase(scope)) { + return List.of(SCOPE_TEST, SCOPE_COMPILE, SCOPE_PROVIDED, SCOPE_SYSTEM, SCOPE_RUNTIME); + } + return List.of(); + } } diff --git a/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/MavenTargetLocation.java b/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/MavenTargetLocation.java index 777617eac7..5a42937b49 100644 --- a/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/MavenTargetLocation.java +++ b/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/MavenTargetLocation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2021 Christoph Läubrich + * Copyright (c) 2018, 2022 Christoph Läubrich * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at @@ -27,6 +27,7 @@ import java.util.Optional; import java.util.Set; import java.util.function.Predicate; +import java.util.stream.Collectors; import org.apache.commons.io.output.StringBuilderWriter; import org.apache.maven.RepositoryUtils; @@ -88,10 +89,13 @@ public class MavenTargetLocation extends AbstractBundleContainer { public static final String ATTRIBUTE_INSTRUCTIONS_REFERENCE = "reference"; public static final String ATTRIBUTE_DEPENDENCY_DEPTH = "includeDependencyDepth"; + @Deprecated public static final String ATTRIBUTE_DEPENDENCY_SCOPE = "includeDependencyScope"; + public static final String ATTRIBUTE_DEPENDENCY_SCOPES = "includeDependencyScopes"; public static final String ATTRIBUTE_INCLUDE_SOURCE = "includeSource"; public static final String ATTRIBUTE_MISSING_META_DATA = "missingManifest"; - public static final String DEFAULT_DEPENDENCY_SCOPE = ""; + public static final List DEFAULT_DEPENDENCY_SCOPES = List + .of(org.apache.maven.artifact.Artifact.SCOPE_COMPILE); public static final MissingMetadataMode DEFAULT_METADATA_MODE = MissingMetadataMode.GENERATE; public static final String DEFAULT_PACKAGE_TYPE = "jar"; public static final String POM_PACKAGE_TYPE = "pom"; @@ -99,7 +103,7 @@ public class MavenTargetLocation extends AbstractBundleContainer { public static final String DEPENDENCYNODE_ROOT = "dependencynode.root"; public static final DependencyDepth DEFAULT_INCLUDE_MODE = DependencyDepth.NONE; - private final String dependencyScope; + private final Collection dependencyScopes; private final MissingMetadataMode metadataMode; private TargetBundles targetBundles; @@ -115,7 +119,7 @@ public class MavenTargetLocation extends AbstractBundleContainer { public MavenTargetLocation(String label, Collection rootDependecies, Collection extraRepositories, MissingMetadataMode metadataMode, - DependencyDepth dependencyDepth, String dependencyScope, boolean includeSource, + DependencyDepth dependencyDepth, Collection dependencyScopes, boolean includeSource, Collection instructions, Collection excludes, IFeature featureTemplate) { this.label = label; this.dependencyDepth = dependencyDepth; @@ -123,7 +127,7 @@ public MavenTargetLocation(String label, Collection rootD this.roots = new ArrayList<>(rootDependecies); this.extraRepositories = Collections.unmodifiableList(new ArrayList<>(extraRepositories)); this.metadataMode = metadataMode; - this.dependencyScope = dependencyScope; + this.dependencyScopes = dependencyScopes; this.includeSource = includeSource; for (BNDInstructions instr : instructions) { instructionsMap.put(instr.getKey(), instr); @@ -243,7 +247,7 @@ private Artifact resolveDependency(MavenTargetDependency root, IMaven maven, Lis } if (depth == DependencyDepth.DIRECT || depth == DependencyDepth.INFINITE) { ICallable callable = new DependencyNodeGenerator(root, artifact, depth, - dependencyScope, repositories, this); + dependencyScopes, repositories, this); PreorderNodeListGenerator dependecies; if (workspaceProject == null) { dependecies = maven.createExecutionContext().execute(callable, subMonitor); @@ -359,7 +363,8 @@ public VersionRangeResult call(IMavenExecutionContext context, IProgressMonitor return null; } - return new MavenTargetLocation(label, latest, extraRepositories, metadataMode, dependencyDepth, dependencyScope, + return new MavenTargetLocation(label, latest, extraRepositories, metadataMode, dependencyDepth, + dependencyScopes, includeSource, instructionsMap.values(), excludedArtifacts, featureTemplate); } @@ -369,7 +374,7 @@ public List getRoots() { } public MavenTargetLocation withInstructions(Collection instructions) { - return new MavenTargetLocation(label, roots, extraRepositories, metadataMode, dependencyDepth, dependencyScope, + return new MavenTargetLocation(label, roots, extraRepositories, metadataMode, dependencyDepth, dependencyScopes, includeSource, instructions, excludedArtifacts, featureTemplate); } @@ -433,7 +438,7 @@ public String getLocation(boolean resolve) throws CoreException { @Override public int hashCode() { - return Objects.hash(roots, dependencyScope, failedArtifacts, metadataMode); + return Objects.hash(roots, dependencyScopes, failedArtifacts, metadataMode); } @Override @@ -448,7 +453,7 @@ public boolean equals(Object obj) { return false; } MavenTargetLocation other = (MavenTargetLocation) obj; - return Objects.equals(roots, other.roots) && Objects.equals(dependencyScope, other.dependencyScope) + return Objects.equals(roots, other.roots) && Objects.equals(dependencyScopes, other.dependencyScopes) && Objects.equals(failedArtifacts, other.failedArtifacts); } @@ -462,7 +467,7 @@ public String serialize() { xml.append(" getDependencyScopes() { + if (dependencyScopes.isEmpty()) { + return DEFAULT_DEPENDENCY_SCOPES; } - return DEFAULT_DEPENDENCY_SCOPE; + return dependencyScopes; } public DependencyDepth getDependencyDepth() { diff --git a/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/MavenTargetLocationFactory.java b/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/MavenTargetLocationFactory.java index 1a1d707428..6788bacc8b 100644 --- a/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/MavenTargetLocationFactory.java +++ b/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/MavenTargetLocationFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2021 Christoph Läubrich + * Copyright (c) 2018, 2022 Christoph Läubrich * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at @@ -15,6 +15,8 @@ import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashSet; import java.util.List; import java.util.stream.IntStream; @@ -50,6 +52,7 @@ public ITargetLocation getTargetLocation(String type, String serializedXML) thro // fall back to safe default mode = MissingMetadataMode.ERROR; } + @SuppressWarnings("deprecation") String dependencyScope = location.getAttribute(MavenTargetLocation.ATTRIBUTE_DEPENDENCY_SCOPE); List dependencies = new ArrayList<>(); List repositories = new ArrayList<>(); @@ -122,8 +125,17 @@ public ITargetLocation getTargetLocation(String type, String serializedXML) thro dependencyDepth = DependencyDepth.INFINITE; } } + Collection locationScopesSet = new LinkedHashSet<>(); + if (location.hasAttribute(MavenTargetLocation.ATTRIBUTE_DEPENDENCY_SCOPES)) { + String dependencyScopes = location.getAttribute(MavenTargetLocation.ATTRIBUTE_DEPENDENCY_SCOPES); + for (String scope : dependencyScopes.split(",")) { + locationScopesSet.add(scope.strip().toLowerCase()); + } + } else { + locationScopesSet.addAll(MavenTargetDependencyFilter.expandScope(dependencyScope)); + } return new MavenTargetLocation(location.getAttribute(MavenTargetLocation.ATTRIBUTE_LABEL), dependencies, - repositories, mode, dependencyDepth, dependencyScope, + repositories, mode, dependencyDepth, locationScopesSet, Boolean.parseBoolean(location.getAttribute(MavenTargetLocation.ATTRIBUTE_INCLUDE_SOURCE)), instructions, excludes, templateFeature); } catch (Exception e) {