mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
repository libraries: add option to exclude only some transitive dependencies (IDEA-193045)
This commit is contained in:
+27
@@ -0,0 +1,27 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.idea.maven.aether;
|
||||
|
||||
import org.eclipse.aether.artifact.Artifact;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ArtifactDependencyNode {
|
||||
private final Artifact myArtifact;
|
||||
private final List<ArtifactDependencyNode> myDependencies;
|
||||
|
||||
public ArtifactDependencyNode(@NotNull Artifact artifact, @NotNull List<ArtifactDependencyNode> dependencies) {
|
||||
myArtifact = artifact;
|
||||
myDependencies = dependencies;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Artifact getArtifact() {
|
||||
return myArtifact;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<ArtifactDependencyNode> getDependencies() {
|
||||
return myDependencies;
|
||||
}
|
||||
}
|
||||
+88
-6
@@ -10,6 +10,7 @@ import org.eclipse.aether.collection.CollectResult;
|
||||
import org.eclipse.aether.collection.DependencyCollectionException;
|
||||
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
|
||||
import org.eclipse.aether.graph.Dependency;
|
||||
import org.eclipse.aether.graph.DependencyFilter;
|
||||
import org.eclipse.aether.graph.DependencyNode;
|
||||
import org.eclipse.aether.graph.DependencyVisitor;
|
||||
import org.eclipse.aether.impl.DefaultServiceLocator;
|
||||
@@ -151,16 +152,34 @@ public class ArtifactRepositoryManager {
|
||||
);
|
||||
}
|
||||
|
||||
public Collection<File> resolveDependency(String groupId, String artifactId, String version, boolean includeTransitiveDependencies) throws Exception {
|
||||
public Collection<File> resolveDependency(String groupId, String artifactId, String version, boolean includeTransitiveDependencies,
|
||||
List<String> excludedDependencies) throws Exception {
|
||||
final List<File> files = new ArrayList<>();
|
||||
for (Artifact artifact : resolveDependencyAsArtifact(groupId, artifactId, version, EnumSet.of(ArtifactKind.ARTIFACT), includeTransitiveDependencies)) {
|
||||
for (Artifact artifact : resolveDependencyAsArtifact(groupId, artifactId, version, EnumSet.of(ArtifactKind.ARTIFACT), includeTransitiveDependencies,
|
||||
excludedDependencies)) {
|
||||
files.add(artifact.getFile());
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ArtifactDependencyNode collectDependencies(String groupId, String artifactId, String versionConstraint) throws Exception {
|
||||
Set<VersionConstraint> constraints = Collections.singleton(asVersionConstraint(versionConstraint));
|
||||
CollectRequest collectRequest = createCollectRequest(groupId, artifactId, constraints, EnumSet.of(ArtifactKind.ARTIFACT));
|
||||
ArtifactDependencyTreeBuilder builder = new ArtifactDependencyTreeBuilder();
|
||||
DependencyNode root = ourSystem.collectDependencies(mySession, collectRequest).getRoot();
|
||||
if (root.getArtifact() == null && root.getChildren().size() == 1) {
|
||||
root = root.getChildren().get(0);
|
||||
}
|
||||
root.accept(new TreeDependencyVisitor(new FilteringDependencyVisitor(builder, createScopeFilter())));
|
||||
return builder.getRoot();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<Artifact> resolveDependencyAsArtifact(String groupId, String artifactId, String versionConstraint, Set<ArtifactKind> artifactKinds, boolean includeTransitiveDependencies) throws Exception {final List<Artifact> artifacts = new ArrayList<>();
|
||||
public Collection<Artifact> resolveDependencyAsArtifact(String groupId, String artifactId, String versionConstraint,
|
||||
Set<ArtifactKind> artifactKinds, boolean includeTransitiveDependencies,
|
||||
List<String> excludedDependencies) throws Exception {
|
||||
final List<Artifact> artifacts = new ArrayList<>();
|
||||
final Set<VersionConstraint> constraints = Collections.singleton(asVersionConstraint(versionConstraint));
|
||||
for (ArtifactKind kind : artifactKinds) {
|
||||
// RepositorySystem.resolveDependencies() ignores classifiers, so we need to set classifiers explicitly for discovered dependencies.
|
||||
@@ -172,9 +191,11 @@ public class ArtifactRepositoryManager {
|
||||
mySession, createCollectRequest(groupId, artifactId, constraints, EnumSet.of(kind))
|
||||
);
|
||||
final ArtifactRequestBuilder builder = new ArtifactRequestBuilder(kind);
|
||||
collectResult.getRoot().accept(new TreeDependencyVisitor(
|
||||
new FilteringDependencyVisitor(builder, DependencyFilterUtils.classpathFilter(JavaScopes.COMPILE, JavaScopes.RUNTIME))
|
||||
));
|
||||
DependencyFilter filter = createScopeFilter();
|
||||
if (!excludedDependencies.isEmpty()) {
|
||||
filter = DependencyFilterUtils.andFilter(filter, new ExcludeDependenciesFilter(excludedDependencies));
|
||||
}
|
||||
collectResult.getRoot().accept(new TreeDependencyVisitor(new FilteringDependencyVisitor(builder, filter)));
|
||||
requests = builder.getRequests();
|
||||
}
|
||||
else {
|
||||
@@ -220,6 +241,11 @@ public class ArtifactRepositoryManager {
|
||||
return artifacts;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static DependencyFilter createScopeFilter() {
|
||||
return DependencyFilterUtils.classpathFilter(JavaScopes.COMPILE, JavaScopes.RUNTIME);
|
||||
}
|
||||
|
||||
public List<Version> getAvailableVersions(String groupId, String artifactId, String versionConstraint, final ArtifactKind artifactKind) throws Exception {
|
||||
final VersionRangeResult result = ourSystem.resolveVersionRange(
|
||||
mySession, createVersionRangeRequest(groupId, artifactId, asVersionConstraint(versionConstraint), artifactKind)
|
||||
@@ -325,4 +351,60 @@ public class ArtifactRepositoryManager {
|
||||
return myRequests;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ExcludeDependenciesFilter implements DependencyFilter {
|
||||
private final HashSet<String> myExcludedDependencies;
|
||||
|
||||
public ExcludeDependenciesFilter(List<String> excludedDependencies) {
|
||||
myExcludedDependencies = new HashSet<>(excludedDependencies);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(DependencyNode node, List<DependencyNode> parents) {
|
||||
Artifact artifact = node.getArtifact();
|
||||
if (artifact != null && myExcludedDependencies.contains(artifact.getGroupId() + ":" + artifact.getArtifactId())) {
|
||||
return false;
|
||||
}
|
||||
for (DependencyNode parent : parents) {
|
||||
Artifact parentArtifact = parent.getArtifact();
|
||||
if (parentArtifact != null && myExcludedDependencies.contains(parentArtifact.getGroupId() + ":" + parentArtifact.getArtifactId())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ArtifactDependencyTreeBuilder implements DependencyVisitor {
|
||||
private final List<List<ArtifactDependencyNode>> myCurrentChildren = new ArrayList<>();
|
||||
|
||||
public ArtifactDependencyTreeBuilder() {
|
||||
myCurrentChildren.add(new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visitEnter(DependencyNode node) {
|
||||
Artifact artifact = node.getArtifact();
|
||||
if (artifact == null) return false;
|
||||
|
||||
myCurrentChildren.add(new ArrayList<>());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visitLeave(DependencyNode node) {
|
||||
Artifact artifact = node.getArtifact();
|
||||
if (artifact != null) {
|
||||
List<ArtifactDependencyNode> last = myCurrentChildren.get(myCurrentChildren.size() - 1);
|
||||
myCurrentChildren.remove(myCurrentChildren.size() - 1);
|
||||
myCurrentChildren.get(myCurrentChildren.size() - 1).add(new ArtifactDependencyNode(artifact, last));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public ArtifactDependencyNode getRoot() {
|
||||
List<ArtifactDependencyNode> rootNodes = myCurrentChildren.get(0);
|
||||
return rootNodes.isEmpty() ? null : rootNodes.get(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+46
-5
@@ -18,9 +18,11 @@ package org.jetbrains.idea.maven.aether;
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.eclipse.aether.artifact.Artifact;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
@@ -36,17 +38,56 @@ public class ArtifactRepositoryManagerTest extends UsefulTestCase {
|
||||
}
|
||||
|
||||
public void testResolveTransitively() throws Exception {
|
||||
Collection<File> files = myRepositoryManager.resolveDependency("junit", "junit", "4.12", true);
|
||||
assertSameElements(ContainerUtil.map(files, File::getName), "junit-4.12.jar", "hamcrest-core-1.3.jar");
|
||||
Collection<File> files = myRepositoryManager.resolveDependency("junit", "junit", "4.12", true, Collections.emptyList());
|
||||
assertFileNames(files, "junit-4.12.jar", "hamcrest-core-1.3.jar");
|
||||
}
|
||||
|
||||
public void testResolveNonTransitively() throws Exception {
|
||||
Collection<File> files = myRepositoryManager.resolveDependency("junit", "junit", "4.12", false);
|
||||
assertSameElements(ContainerUtil.map(files, File::getName), "junit-4.12.jar");
|
||||
Collection<File> files = myRepositoryManager.resolveDependency("junit", "junit", "4.12", false, Collections.emptyList());
|
||||
assertFileNames(files, "junit-4.12.jar");
|
||||
}
|
||||
|
||||
public void testExcludeDirectDependency() throws Exception {
|
||||
Collection<File> all = myRepositoryManager.resolveDependency("junit", "junit", "4.12", true, Collections.singletonList("org.hamcrest:wrong"));
|
||||
assertFileNames(all, "junit-4.12.jar", "hamcrest-core-1.3.jar");
|
||||
Collection<File> excluded = myRepositoryManager.resolveDependency("junit", "junit", "4.12", true, Collections.singletonList("org.hamcrest:hamcrest-core"));
|
||||
assertFileNames(excluded, "junit-4.12.jar");
|
||||
}
|
||||
|
||||
public void testExcludeDependenciesTransitively() throws Exception {
|
||||
Collection<File> all = myRepositoryManager.resolveDependency("org.apache.httpcomponents", "fluent-hc", "4.5.5", true, Collections.emptyList());
|
||||
assertFileNames(all, "fluent-hc-4.5.5.jar", "httpclient-4.5.5.jar", "httpcore-4.4.9.jar", "commons-logging-1.2.jar", "commons-codec-1.10.jar");
|
||||
Collection<File> excluded = myRepositoryManager.resolveDependency("org.apache.httpcomponents", "fluent-hc", "4.5.5", true, Collections.singletonList("org.apache.httpcomponents:httpclient"));
|
||||
assertFileNames(excluded, "fluent-hc-4.5.5.jar", "commons-logging-1.2.jar");
|
||||
}
|
||||
|
||||
public void testResolveRuntimeDependencies() throws Exception {
|
||||
Collection<File> files = myRepositoryManager.resolveDependency("com.netflix.feign", "feign-jackson", "8.18.0", true);
|
||||
Collection<File> files = myRepositoryManager.resolveDependency("com.netflix.feign", "feign-jackson", "8.18.0", true,
|
||||
Collections.emptyList());
|
||||
assertContainsElements(ContainerUtil.map(files, File::getName), "feign-core-8.18.0.jar");
|
||||
}
|
||||
|
||||
public void testCollectDependencies() throws Exception {
|
||||
ArtifactDependencyNode result = myRepositoryManager.collectDependencies("org.apache.httpcomponents", "fluent-hc", "4.5.5");
|
||||
assertNotNull(result);
|
||||
assertCoordinates(result.getArtifact(), "org.apache.httpcomponents", "fluent-hc", "4.5.5");
|
||||
assertEquals(2, result.getDependencies().size());
|
||||
ArtifactDependencyNode first = result.getDependencies().get(0);
|
||||
ArtifactDependencyNode second = result.getDependencies().get(1);
|
||||
assertCoordinates(first.getArtifact(), "org.apache.httpcomponents", "httpclient", "4.5.5");
|
||||
assertCoordinates(second.getArtifact(), "commons-logging", "commons-logging", "1.2");
|
||||
assertEquals(2, first.getDependencies().size());
|
||||
assertCoordinates(first.getDependencies().get(0).getArtifact(), "org.apache.httpcomponents", "httpcore", "4.4.9");
|
||||
assertCoordinates(first.getDependencies().get(1).getArtifact(), "commons-codec", "commons-codec", "1.10");
|
||||
}
|
||||
|
||||
private static void assertCoordinates(Artifact artifact, String groupId, String artifactId, String version) {
|
||||
assertEquals(groupId, artifact.getGroupId());
|
||||
assertEquals(artifactId, artifact.getArtifactId());
|
||||
assertEquals(version, artifact.getVersion());
|
||||
}
|
||||
|
||||
private static void assertFileNames(Collection<File> files, String... expectedNames) {
|
||||
assertSameElements(ContainerUtil.map(files, File::getName), expectedNames);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.concurrency.AsyncPromise;
|
||||
import org.jetbrains.concurrency.Promise;
|
||||
import org.jetbrains.idea.maven.aether.ArtifactDependencyNode;
|
||||
import org.jetbrains.idea.maven.aether.ArtifactKind;
|
||||
import org.jetbrains.idea.maven.aether.ArtifactRepositoryManager;
|
||||
import org.jetbrains.idea.maven.aether.ProgressConsumer;
|
||||
@@ -265,6 +266,27 @@ public class JarRepositoryManager {
|
||||
return submitBackgroundJob(project, "Looking up available versions for " + libraryDescription.getDisplayName(), new VersionResolveJob(libraryDescription, repos));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ArtifactDependencyNode loadDependenciesTree(@NotNull RepositoryLibraryDescription description, @NotNull String version, Project project) {
|
||||
List<RemoteRepositoryDescription> repositories = RemoteRepositoriesConfiguration.getInstance(project).getRepositories();
|
||||
return submitModalJob(project, "Resolving Maven Dependencies", new AetherJob<ArtifactDependencyNode>(repositories) {
|
||||
@Override
|
||||
protected String getProgressText() {
|
||||
return "Loading dependencies of " + description.getMavenCoordinates(version);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ArtifactDependencyNode perform(ProgressIndicator progress, ArtifactRepositoryManager manager) throws Exception {
|
||||
return manager.collectDependencies(description.getGroupId(), description.getArtifactId(), version);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ArtifactDependencyNode getDefaultResult() {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void notifyArtifactsDownloaded(Project project, Collection<OrderRoot> roots) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final String title = "The following files were downloaded:";
|
||||
@@ -533,7 +555,7 @@ public class JarRepositoryManager {
|
||||
final String version = myDesc.getVersion();
|
||||
try {
|
||||
return manager.resolveDependencyAsArtifact(myDesc.getGroupId(), myDesc.getArtifactId(), version, myKinds,
|
||||
myDesc.isIncludeTransitiveDependencies());
|
||||
myDesc.isIncludeTransitiveDependencies(), myDesc.getExcludedDependencies());
|
||||
}
|
||||
catch (TransferCancelledException e) {
|
||||
throw new ProcessCanceledException(e);
|
||||
@@ -548,7 +570,7 @@ public class JarRepositoryManager {
|
||||
}
|
||||
try {
|
||||
return manager.resolveDependencyAsArtifact(myDesc.getGroupId(), myDesc.getArtifactId(), resolvedVersion, myKinds,
|
||||
myDesc.isIncludeTransitiveDependencies());
|
||||
myDesc.isIncludeTransitiveDependencies(), myDesc.getExcludedDependencies());
|
||||
}
|
||||
catch (TransferCancelledException e1) {
|
||||
throw new ProcessCanceledException(e1);
|
||||
|
||||
+2
-1
@@ -38,7 +38,8 @@ public class RepositoryLibrarySupportInModuleConfigurable extends FrameworkSuppo
|
||||
public RepositoryLibrarySupportInModuleConfigurable(@Nullable Project project, @NotNull RepositoryLibraryDescription libraryDescription) {
|
||||
this.libraryDescription = libraryDescription;
|
||||
RepositoryLibraryProperties defaultProperties = libraryDescription.createDefaultProperties();
|
||||
this.model = new RepositoryLibraryPropertiesModel(defaultProperties.getVersion(), false, false, defaultProperties.isIncludeTransitiveDependencies());
|
||||
this.model = new RepositoryLibraryPropertiesModel(defaultProperties.getVersion(), false, false, defaultProperties.isIncludeTransitiveDependencies(),
|
||||
defaultProperties.getExcludedDependencies());
|
||||
editor = new RepositoryLibraryPropertiesEditor(project, model, libraryDescription);
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -50,7 +50,8 @@ public class RepositoryLibraryWithDescriptionEditor
|
||||
RepositoryLibraryPropertiesModel model = new RepositoryLibraryPropertiesModel(
|
||||
properties.getVersion(),
|
||||
RepositoryUtils.libraryHasSources(myEditorComponent.getLibraryEditor()),
|
||||
RepositoryUtils.libraryHasJavaDocs(myEditorComponent.getLibraryEditor()), properties.isIncludeTransitiveDependencies());
|
||||
RepositoryUtils.libraryHasJavaDocs(myEditorComponent.getLibraryEditor()), properties.isIncludeTransitiveDependencies(),
|
||||
properties.getExcludedDependencies());
|
||||
|
||||
final Project project = myEditorComponent.getProject();
|
||||
assert project != null : "EditorComponent's project must not be null in order to be used with RepositoryLibraryWithDescriptionEditor";
|
||||
@@ -65,6 +66,7 @@ public class RepositoryLibraryWithDescriptionEditor
|
||||
}
|
||||
myEditorComponent.getProperties().changeVersion(model.getVersion());
|
||||
myEditorComponent.getProperties().setIncludeTransitiveDependencies(model.isIncludeTransitiveDependencies());
|
||||
myEditorComponent.getProperties().setExcludedDependencies(model.getExcludedDependencies());
|
||||
if (wasGeneratedName) {
|
||||
myEditorComponent.renameLibrary(RepositoryLibraryType.getInstance().getDescription(properties));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.jarRepository.settings;
|
||||
|
||||
import com.intellij.openapi.ui.DialogBuilder;
|
||||
import com.intellij.openapi.ui.panel.ComponentPanelBuilder;
|
||||
import com.intellij.ui.CheckboxTree;
|
||||
import com.intellij.ui.CheckboxTreeBase;
|
||||
import com.intellij.ui.CheckedTreeNode;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
import com.intellij.util.ui.UI;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import org.eclipse.aether.artifact.Artifact;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.maven.aether.ArtifactDependencyNode;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.*;
|
||||
|
||||
class DependencyExclusionEditor {
|
||||
private final CheckboxTree myDependenciesTree;
|
||||
private final CheckedTreeNode myRootNode;
|
||||
private final JPanel myMainPanel;
|
||||
|
||||
public DependencyExclusionEditor(ArtifactDependencyNode root, JPanel parentComponent) {
|
||||
myMainPanel = parentComponent;
|
||||
myRootNode = createDependencyTreeNode(root);
|
||||
CheckboxTreeBase.CheckPolicy policy = new CheckboxTreeBase.CheckPolicy(false, true, true, false);
|
||||
myDependenciesTree = new CheckboxTree(new CheckboxTree.CheckboxTreeCellRenderer() {
|
||||
{
|
||||
myIgnoreInheritance = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customizeRenderer(JTree tree,
|
||||
Object value,
|
||||
boolean selected,
|
||||
boolean expanded,
|
||||
boolean leaf,
|
||||
int row,
|
||||
boolean hasFocus) {
|
||||
if (!(value instanceof CheckedTreeNode)) return;
|
||||
|
||||
Object userObject = ((CheckedTreeNode)value).getUserObject();
|
||||
if (!(userObject instanceof Artifact)) return;
|
||||
|
||||
Artifact artifact = (Artifact)userObject;
|
||||
getTextRenderer().append(artifact.getGroupId() + ":" + artifact.getArtifactId(), SimpleTextAttributes.REGULAR_ATTRIBUTES, true);
|
||||
getTextRenderer().append(":" + artifact.getVersion(), SimpleTextAttributes.GRAYED_ATTRIBUTES, true);
|
||||
}
|
||||
}, myRootNode, policy);
|
||||
myDependenciesTree.setRootVisible(false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Set<String> selectExcludedDependencies(List<String> excludedDependencies) {
|
||||
uncheckExcludedNodes(myRootNode, new HashSet<>(excludedDependencies), false);
|
||||
TreeUtil.expandAll(myDependenciesTree);
|
||||
ComponentPanelBuilder panelBuilder =
|
||||
UI.PanelFactory.panel(new JBScrollPane(myDependenciesTree))
|
||||
.withLabel("Specify which transitive dependencies should be included into the library.")
|
||||
.moveLabelOnTop();
|
||||
DialogBuilder dialogBuilder =
|
||||
new DialogBuilder(myMainPanel)
|
||||
.title("Configure Transitive Dependencies")
|
||||
.centerPanel(panelBuilder.createPanel());
|
||||
dialogBuilder.setPreferredFocusComponent(myDependenciesTree);
|
||||
|
||||
if (dialogBuilder.showAndGet()) {
|
||||
return collectUncheckedNodes(myRootNode, new LinkedHashSet<>());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void uncheckExcludedNodes(CheckedTreeNode node, Set<String> excluded, boolean parentIsExcluded) {
|
||||
boolean isExcluded = parentIsExcluded || excluded.contains(getGroupAndArtifactId(node));
|
||||
node.setChecked(!isExcluded);
|
||||
Enumeration children = node.children();
|
||||
while (children.hasMoreElements()) {
|
||||
Object child = children.nextElement();
|
||||
uncheckExcludedNodes((CheckedTreeNode)child, excluded, isExcluded);
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<String> collectUncheckedNodes(CheckedTreeNode node, Set<String> result) {
|
||||
if (node.isChecked()) {
|
||||
Enumeration children = node.children();
|
||||
while (children.hasMoreElements()) {
|
||||
Object child = children.nextElement();
|
||||
collectUncheckedNodes((CheckedTreeNode)child, result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.add(getGroupAndArtifactId(node));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getGroupAndArtifactId(CheckedTreeNode node) {
|
||||
Artifact artifact = (Artifact)node.getUserObject();
|
||||
return artifact.getGroupId() + ":" + artifact.getArtifactId();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static CheckedTreeNode createDependencyTreeNode(ArtifactDependencyNode node) {
|
||||
CheckedTreeNode treeNode = new CheckedTreeNode(node.getArtifact());
|
||||
for (ArtifactDependencyNode dependency : node.getDependencies()) {
|
||||
treeNode.add(createDependencyTreeNode(dependency));
|
||||
}
|
||||
return treeNode;
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -135,14 +135,14 @@
|
||||
<text value="Download &JavaDocs"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="75440" class="com.intellij.ui.components.JBCheckBox" binding="myIncludeTransitiveDepsCheckBox">
|
||||
<grid id="2c1fe" binding="myTransitiveDependenciesPanel" layout-manager="FlowLayout" hgap="0" vgap="0" flow-align="1">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Include &transitive dependencies"/>
|
||||
</properties>
|
||||
</component>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children/>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
|
||||
+58
-6
@@ -19,15 +19,21 @@ import com.google.common.base.Strings;
|
||||
import com.intellij.jarRepository.JarRepositoryManager;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.ui.CollectionComboBoxModel;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.ui.components.labels.SwingActionLink;
|
||||
import com.intellij.util.containers.JBIterable;
|
||||
import com.intellij.util.ui.ThreeStateCheckBox;
|
||||
import com.intellij.util.ui.UI;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.maven.aether.ArtifactDependencyNode;
|
||||
import org.jetbrains.idea.maven.utils.library.RepositoryLibraryDescription;
|
||||
import org.jetbrains.idea.maven.utils.library.propertiesEditor.RepositoryLibraryPropertiesModel;
|
||||
|
||||
@@ -39,11 +45,11 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
public class RepositoryLibraryPropertiesEditor {
|
||||
private static final Logger LOG = Logger.getInstance(RepositoryLibraryPropertiesEditor.class);
|
||||
@NotNull private final Project project;
|
||||
State currentState;
|
||||
List<String> versions;
|
||||
@@ -59,10 +65,12 @@ public class RepositoryLibraryPropertiesEditor {
|
||||
private JBCheckBox downloadSourcesCheckBox;
|
||||
private JBCheckBox downloadJavaDocsCheckBox;
|
||||
private JBLabel mavenCoordinates;
|
||||
private JBCheckBox myIncludeTransitiveDepsCheckBox;
|
||||
private final ThreeStateCheckBox myIncludeTransitiveDepsCheckBox;
|
||||
private JPanel myPropertiesPanel;
|
||||
private JPanel myTransitiveDependenciesPanel;
|
||||
|
||||
@NotNull private final ModelChangeListener onChangeListener;
|
||||
private final SwingActionLink myManageDependenciesLink;
|
||||
|
||||
public interface ModelChangeListener {
|
||||
void onChange(RepositoryLibraryPropertiesEditor editor);
|
||||
@@ -90,7 +98,18 @@ public class RepositoryLibraryPropertiesEditor {
|
||||
this.project = project == null ? ProjectManager.getInstance().getDefaultProject() : project;
|
||||
repositoryLibraryDescription = description;
|
||||
mavenCoordinates.setCopyable(true);
|
||||
myIncludeTransitiveDepsCheckBox.setVisible(allowExcludingTransitiveDependencies);
|
||||
myIncludeTransitiveDepsCheckBox = new ThreeStateCheckBox(UIUtil.replaceMnemonicAmpersand("Include &transitive dependencies"));
|
||||
myIncludeTransitiveDepsCheckBox.setThirdStateEnabled(false);
|
||||
myTransitiveDependenciesPanel.add(myIncludeTransitiveDepsCheckBox);
|
||||
myManageDependenciesLink = new SwingActionLink(new AbstractAction("Configure") {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
configureTransitiveDependencies();
|
||||
}
|
||||
});
|
||||
myManageDependenciesLink.setBorder(UI.Borders.emptyLeft(10));
|
||||
myTransitiveDependenciesPanel.add(myManageDependenciesLink);
|
||||
myTransitiveDependenciesPanel.setVisible(allowExcludingTransitiveDependencies);
|
||||
myReloadButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
@@ -104,9 +123,25 @@ public class RepositoryLibraryPropertiesEditor {
|
||||
mavenCoordinates.setText(repositoryLibraryDescription.getMavenCoordinates(model.getVersion()));
|
||||
}
|
||||
};
|
||||
updateManageDependenciesLink();
|
||||
reloadVersionsAsync();
|
||||
}
|
||||
|
||||
private void configureTransitiveDependencies() {
|
||||
String selectedVersion = getSelectedVersion();
|
||||
LOG.assertTrue(selectedVersion != null);
|
||||
|
||||
ArtifactDependencyNode root = JarRepositoryManager.loadDependenciesTree(repositoryLibraryDescription, selectedVersion, project);
|
||||
if (root == null) return;
|
||||
|
||||
Set<String> dependencies = new DependencyExclusionEditor(root, mainPanel).selectExcludedDependencies(model.getExcludedDependencies());
|
||||
if (dependencies != null) {
|
||||
model.setExcludedDependencies(dependencies);
|
||||
updateIncludeTransitiveDepsCheckBoxState();
|
||||
onChangeListener.onChange(this);
|
||||
}
|
||||
}
|
||||
|
||||
private static VersionKind getVersionKind(String version) {
|
||||
if (Strings.isNullOrEmpty(version)) {
|
||||
return VersionKind.Unselected;
|
||||
@@ -168,6 +203,7 @@ public class RepositoryLibraryPropertiesEditor {
|
||||
int selection = getSelection(model.getVersion(), versions);
|
||||
versionSelector.setSelectedIndex(selection);
|
||||
onChangeListener.onChange(this);
|
||||
updateManageDependenciesLink();
|
||||
}
|
||||
|
||||
private VersionKind getSelectedVersionKind() {
|
||||
@@ -225,6 +261,7 @@ public class RepositoryLibraryPropertiesEditor {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
model.setVersion(getSelectedVersion());
|
||||
onChangeListener.onChange(RepositoryLibraryPropertiesEditor.this);
|
||||
updateManageDependenciesLink();
|
||||
}
|
||||
});
|
||||
downloadSourcesCheckBox.setSelected(model.isDownloadSources());
|
||||
@@ -243,16 +280,31 @@ public class RepositoryLibraryPropertiesEditor {
|
||||
onChangeListener.onChange(RepositoryLibraryPropertiesEditor.this);
|
||||
}
|
||||
});
|
||||
myIncludeTransitiveDepsCheckBox.setSelected(model.isIncludeTransitiveDependencies());
|
||||
updateIncludeTransitiveDepsCheckBoxState();
|
||||
myIncludeTransitiveDepsCheckBox.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
model.setIncludeTransitiveDependencies(myIncludeTransitiveDepsCheckBox.isSelected());
|
||||
updateManageDependenciesLink();
|
||||
ThreeStateCheckBox.State state = myIncludeTransitiveDepsCheckBox.getState();
|
||||
if (state != ThreeStateCheckBox.State.DONT_CARE) {
|
||||
model.setExcludedDependencies(Collections.emptyList());
|
||||
}
|
||||
model.setIncludeTransitiveDependencies(state != ThreeStateCheckBox.State.NOT_SELECTED);
|
||||
onChangeListener.onChange(RepositoryLibraryPropertiesEditor.this);
|
||||
}
|
||||
});
|
||||
updateManageDependenciesLink();
|
||||
}
|
||||
|
||||
private void updateIncludeTransitiveDepsCheckBoxState() {
|
||||
myIncludeTransitiveDepsCheckBox.setState(!model.isIncludeTransitiveDependencies() ? ThreeStateCheckBox.State.NOT_SELECTED :
|
||||
model.getExcludedDependencies().isEmpty() ? ThreeStateCheckBox.State.SELECTED : ThreeStateCheckBox.State.DONT_CARE);
|
||||
}
|
||||
|
||||
private void updateManageDependenciesLink() {
|
||||
boolean enable = myIncludeTransitiveDepsCheckBox.getState() != ThreeStateCheckBox.State.NOT_SELECTED && getSelectedVersion() != null;
|
||||
myManageDependenciesLink.setEnabled(enable);
|
||||
}
|
||||
|
||||
private void versionsLoaded(final @Nullable List<String> versions) {
|
||||
this.versions = versions;
|
||||
|
||||
+4
-2
@@ -80,7 +80,8 @@ abstract class ConvertToRepositoryLibraryActionBase(protected val context: Struc
|
||||
|
||||
private fun downloadLibraryAndReplace(library: LibraryEx,
|
||||
mavenCoordinates: JpsMavenRepositoryLibraryDescriptor) {
|
||||
val libraryProperties = RepositoryLibraryProperties(mavenCoordinates.groupId, mavenCoordinates.artifactId, mavenCoordinates.version, mavenCoordinates.isIncludeTransitiveDependencies)
|
||||
val libraryProperties = RepositoryLibraryProperties(mavenCoordinates.groupId, mavenCoordinates.artifactId, mavenCoordinates.version,
|
||||
mavenCoordinates.isIncludeTransitiveDependencies, mavenCoordinates.excludedDependencies)
|
||||
val hasSources = RepositoryUtils.libraryHasSources(library)
|
||||
val hasJavadoc = RepositoryUtils.libraryHasJavaDocs(library)
|
||||
LOG.debug("Resolving $mavenCoordinates")
|
||||
@@ -151,7 +152,8 @@ abstract class ConvertToRepositoryLibraryActionBase(protected val context: Struc
|
||||
return null
|
||||
}
|
||||
|
||||
return JpsMavenRepositoryLibraryDescriptor(dialog.coordinateText, dialog.includeTransitiveDependencies)
|
||||
return JpsMavenRepositoryLibraryDescriptor(dialog.coordinateText, dialog.includeTransitiveDependencies,
|
||||
emptyList<String>())
|
||||
}
|
||||
|
||||
private fun replaceByLibrary(library: Library, configuration: NewLibraryConfiguration) {
|
||||
|
||||
+2
-1
@@ -74,7 +74,8 @@ public class RepositoryLibrarySupport {
|
||||
libraryDescription.getGroupId(),
|
||||
libraryDescription.getArtifactId(),
|
||||
model.getVersion(),
|
||||
model.isIncludeTransitiveDependencies());
|
||||
model.isIncludeTransitiveDependencies(),
|
||||
model.getExcludedDependencies());
|
||||
final LibraryEx library = (LibraryEx)modifiableModel.createLibrary(
|
||||
LibraryEditingUtil.suggestNewLibraryName(modifiableModel, RepositoryLibraryType.getInstance().getDescription(libraryProperties)),
|
||||
RepositoryLibraryType.REPOSITORY_LIBRARY_KIND);
|
||||
|
||||
+21
-4
@@ -16,27 +16,35 @@
|
||||
package org.jetbrains.idea.maven.utils.library.propertiesEditor;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class RepositoryLibraryPropertiesModel {
|
||||
private String version;
|
||||
private boolean downloadSources;
|
||||
private boolean downloadJavaDocs;
|
||||
private boolean includeTransitiveDependencies;
|
||||
private List<String> myExcludedDependencies;
|
||||
|
||||
public RepositoryLibraryPropertiesModel(String version, boolean downloadSources, boolean downloadJavaDocs) {
|
||||
this(version, downloadSources, downloadJavaDocs, true);
|
||||
this(version, downloadSources, downloadJavaDocs, true, ContainerUtil.emptyList());
|
||||
}
|
||||
|
||||
public RepositoryLibraryPropertiesModel(String version, boolean downloadSources, boolean downloadJavaDocs,
|
||||
boolean includeTransitiveDependencies) {
|
||||
boolean includeTransitiveDependencies, List<String> excludedDependencies) {
|
||||
this.version = version;
|
||||
this.downloadSources = downloadSources;
|
||||
this.downloadJavaDocs = downloadJavaDocs;
|
||||
this.includeTransitiveDependencies = includeTransitiveDependencies;
|
||||
myExcludedDependencies = new ArrayList<>(excludedDependencies);
|
||||
}
|
||||
|
||||
public RepositoryLibraryPropertiesModel clone() {
|
||||
return new RepositoryLibraryPropertiesModel(version, downloadSources, downloadJavaDocs, includeTransitiveDependencies);
|
||||
return new RepositoryLibraryPropertiesModel(version, downloadSources, downloadJavaDocs, includeTransitiveDependencies,
|
||||
new ArrayList<>(myExcludedDependencies));
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
@@ -51,6 +59,14 @@ public class RepositoryLibraryPropertiesModel {
|
||||
this.includeTransitiveDependencies = includeTransitiveDependencies;
|
||||
}
|
||||
|
||||
public List<String> getExcludedDependencies() {
|
||||
return myExcludedDependencies;
|
||||
}
|
||||
|
||||
public void setExcludedDependencies(Collection<String> excludedDependencies) {
|
||||
myExcludedDependencies = new ArrayList<>(excludedDependencies);
|
||||
}
|
||||
|
||||
public boolean isDownloadSources() {
|
||||
return downloadSources;
|
||||
}
|
||||
@@ -86,7 +102,7 @@ public class RepositoryLibraryPropertiesModel {
|
||||
if (downloadJavaDocs != model.downloadJavaDocs) return false;
|
||||
if (includeTransitiveDependencies != model.includeTransitiveDependencies) return false;
|
||||
if (version != null ? !version.equals(model.version) : model.version != null) return false;
|
||||
|
||||
if (!myExcludedDependencies.equals(model.myExcludedDependencies)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -96,6 +112,7 @@ public class RepositoryLibraryPropertiesModel {
|
||||
result = 31 * result + (downloadJavaDocs ? 1 : 0);
|
||||
result = 31 * result + (includeTransitiveDependencies ? 1 : 0);
|
||||
result = 31 * result + (version != null ? version.hashCode() : 0);
|
||||
result = 31 * result + myExcludedDependencies.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ public abstract class AbstractTestFrameworkIntegrationTest extends BaseConfigura
|
||||
ArtifactRepositoryManager repoManager) throws Exception {
|
||||
|
||||
Collection<File> files = repoManager.resolveDependency(descriptor.getGroupId(), descriptor.getArtifactId(), descriptor.getVersion(),
|
||||
descriptor.isIncludeTransitiveDependencies());
|
||||
descriptor.isIncludeTransitiveDependencies(), descriptor.getExcludedDependencies());
|
||||
assertFalse("No files retrieved for: " + descriptor.getGroupId(), files.isEmpty());
|
||||
for (File artifact : files) {
|
||||
VirtualFile libJarLocal = LocalFileSystem.getInstance().findFileByIoFile(artifact);
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.roots.libraries;
|
||||
|
||||
import com.intellij.jarRepository.RepositoryLibraryType;
|
||||
import com.intellij.openapi.application.ex.PathManagerEx;
|
||||
import com.intellij.openapi.roots.impl.libraries.LibraryEx;
|
||||
import com.intellij.openapi.roots.impl.libraries.LibraryTableBase;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.roots.ModuleRootManagerTestCase;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.JDOMException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.maven.utils.library.RepositoryLibraryProperties;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class RepositoryLibrarySerializationTest extends ModuleRootManagerTestCase {
|
||||
public void testPlain() throws JDOMException, IOException {
|
||||
RepositoryLibraryProperties properties = loadLibrary("plain");
|
||||
assertEquals("junit", properties.getGroupId());
|
||||
assertEquals("junit", properties.getArtifactId());
|
||||
assertEquals("3.8.1", properties.getVersion());
|
||||
assertTrue(properties.isIncludeTransitiveDependencies());
|
||||
assertEmpty(properties.getExcludedDependencies());
|
||||
}
|
||||
|
||||
public void testWithoutTransitiveDependencies() throws JDOMException, IOException {
|
||||
RepositoryLibraryProperties properties = loadLibrary("without-transitive-dependencies");
|
||||
assertFalse(properties.isIncludeTransitiveDependencies());
|
||||
assertEmpty(properties.getExcludedDependencies());
|
||||
}
|
||||
|
||||
public void testWithExcludedDependencies() throws JDOMException, IOException {
|
||||
RepositoryLibraryProperties properties = loadLibrary("with-excluded-dependencies");
|
||||
assertTrue(properties.isIncludeTransitiveDependencies());
|
||||
assertSameElements(properties.getExcludedDependencies(), "org.apache.httpcomponents:httpclient");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private RepositoryLibraryProperties loadLibrary(String name) throws JDOMException, IOException {
|
||||
String libraryPath = "jps/model-serialization/testData/repositoryLibraries/.idea/libraries/" + name + ".xml";
|
||||
Element element = JDOMUtil.load(PathManagerEx.findFileUnderCommunityHome(libraryPath));
|
||||
LibraryTableBase libraryTable = (LibraryTableBase)LibraryTablesRegistrar.getInstance().getLibraryTable(myProject);
|
||||
libraryTable.loadState(element);
|
||||
LibraryEx library = (LibraryEx)libraryTable.getLibraryByName(name);
|
||||
assertNotNull(library);
|
||||
assertSame(RepositoryLibraryType.REPOSITORY_LIBRARY_KIND, library.getKind());
|
||||
RepositoryLibraryProperties properties = (RepositoryLibraryProperties)library.getProperties();
|
||||
assertNotNull(properties);
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -17,7 +17,7 @@ package org.jetbrains.idea.maven.utils.library;
|
||||
|
||||
import com.intellij.jarRepository.RepositoryLibraryDefinition;
|
||||
import com.intellij.openapi.roots.DependencyScope;
|
||||
import java.util.HashMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import icons.OpenapiIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.jps.model.library.JpsMavenRepositoryLibraryDescriptor;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class RepositoryLibraryDescription {
|
||||
@@ -112,7 +113,7 @@ public class RepositoryLibraryDescription {
|
||||
}
|
||||
|
||||
public RepositoryLibraryProperties createDefaultProperties() {
|
||||
return new RepositoryLibraryProperties(getGroupId(), getArtifactId(), ReleaseVersionId, true);
|
||||
return new RepositoryLibraryProperties(getGroupId(), getArtifactId(), ReleaseVersionId, true, ContainerUtil.emptyList());
|
||||
}
|
||||
|
||||
public String getDisplayName(String version) {
|
||||
|
||||
+41
-8
@@ -3,10 +3,16 @@ package org.jetbrains.idea.maven.utils.library;
|
||||
|
||||
import com.intellij.openapi.roots.libraries.LibraryProperties;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.xmlb.annotations.Attribute;
|
||||
import com.intellij.util.xmlb.annotations.Transient;
|
||||
import com.intellij.util.xmlb.annotations.XCollection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.model.library.JpsMavenRepositoryLibraryDescriptor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
@@ -19,15 +25,19 @@ public class RepositoryLibraryProperties extends LibraryProperties<RepositoryLib
|
||||
}
|
||||
|
||||
public RepositoryLibraryProperties(String mavenId, final boolean includeTransitiveDependencies) {
|
||||
myDescriptor = new JpsMavenRepositoryLibraryDescriptor(mavenId, includeTransitiveDependencies);
|
||||
myDescriptor = new JpsMavenRepositoryLibraryDescriptor(mavenId, includeTransitiveDependencies, Collections.emptyList());
|
||||
}
|
||||
|
||||
public RepositoryLibraryProperties(@NotNull String groupId, @NotNull String artifactId, @NotNull String version) {
|
||||
this(groupId, artifactId, version, true);
|
||||
this(groupId, artifactId, version, true, ContainerUtil.emptyList());
|
||||
}
|
||||
|
||||
public RepositoryLibraryProperties(@NotNull String groupId, @NotNull String artifactId, @NotNull String version, boolean includeTransitiveDependencies) {
|
||||
myDescriptor = new JpsMavenRepositoryLibraryDescriptor(groupId, artifactId, version, includeTransitiveDependencies);
|
||||
public RepositoryLibraryProperties(@NotNull String groupId,
|
||||
@NotNull String artifactId,
|
||||
@NotNull String version,
|
||||
boolean includeTransitiveDependencies, @NotNull List<String> excludedDependencies) {
|
||||
myDescriptor = new JpsMavenRepositoryLibraryDescriptor(groupId, artifactId, version, includeTransitiveDependencies,
|
||||
excludedDependencies);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -56,7 +66,7 @@ public class RepositoryLibraryProperties extends LibraryProperties<RepositoryLib
|
||||
}
|
||||
|
||||
public void setMavenId(String mavenId) {
|
||||
myDescriptor = new JpsMavenRepositoryLibraryDescriptor(mavenId, isIncludeTransitiveDependencies());
|
||||
myDescriptor = new JpsMavenRepositoryLibraryDescriptor(mavenId, isIncludeTransitiveDependencies(), getExcludedDependencies());
|
||||
}
|
||||
|
||||
@Attribute("include-transitive-deps")
|
||||
@@ -65,7 +75,7 @@ public class RepositoryLibraryProperties extends LibraryProperties<RepositoryLib
|
||||
}
|
||||
|
||||
public void setIncludeTransitiveDependencies(boolean value) {
|
||||
myDescriptor = new JpsMavenRepositoryLibraryDescriptor(getMavenId(), value);
|
||||
myDescriptor = new JpsMavenRepositoryLibraryDescriptor(getMavenId(), value, getExcludedDependencies());
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
@@ -81,7 +91,7 @@ public class RepositoryLibraryProperties extends LibraryProperties<RepositoryLib
|
||||
}
|
||||
|
||||
public void changeVersion(String version) {
|
||||
myDescriptor = new JpsMavenRepositoryLibraryDescriptor(getGroupId(), getArtifactId(), version, myDescriptor.isIncludeTransitiveDependencies());
|
||||
myDescriptor = new JpsMavenRepositoryLibraryDescriptor(getGroupId(), getArtifactId(), version, myDescriptor.isIncludeTransitiveDependencies(), myDescriptor.getExcludedDependencies());
|
||||
}
|
||||
|
||||
private String call(Function<JpsMavenRepositoryLibraryDescriptor, String> method) {
|
||||
@@ -89,8 +99,31 @@ public class RepositoryLibraryProperties extends LibraryProperties<RepositoryLib
|
||||
return descriptor != null ? method.apply(descriptor) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of excluded transitive dependencies in {@code "<groupId>:<artifactId>"} format.
|
||||
*/
|
||||
@Transient
|
||||
public List<String> getExcludedDependencies() {
|
||||
return myDescriptor != null ? myDescriptor.getExcludedDependencies() : Collections.emptyList();
|
||||
}
|
||||
|
||||
public void setExcludedDependencies(List<String> dependencyMavenIds) {
|
||||
myDescriptor = new JpsMavenRepositoryLibraryDescriptor(getMavenId(), isIncludeTransitiveDependencies(), dependencyMavenIds);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused") //we need to have a separate method here because XmlSerializer fails if the returned list is unmodifiable
|
||||
@XCollection(propertyElementName = "exclude", elementName = "dependency", valueAttributeName = "maven-id")
|
||||
public List<String> getExcludedDependenciesBean() {
|
||||
return myDescriptor != null ? new ArrayList<>(myDescriptor.getExcludedDependencies()) : new ArrayList<>();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused") //used by XmlSerializer
|
||||
public void setExcludedDependenciesBean(List<String> dependencyMavenIds) {
|
||||
setExcludedDependencies(dependencyMavenIds);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JpsMavenRepositoryLibraryDescriptor getRepositoryLibraryDescriptor() {
|
||||
return myDescriptor != null ? myDescriptor : new JpsMavenRepositoryLibraryDescriptor(null, true);
|
||||
return myDescriptor != null ? myDescriptor : new JpsMavenRepositoryLibraryDescriptor(null, true, Collections.emptyList());
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -147,7 +147,8 @@ public class DependencyResolvingBuilder extends ModuleLevelBuilder{
|
||||
context.processMessage(new ProgressMessage("Resolving '" + lib.getName() + "' library..."));
|
||||
LOG.debug("Downloading missing files for " + lib.getName() + " library: " + required);
|
||||
final Collection<File> resolved = repoManager.resolveDependency(descriptor.getGroupId(), descriptor.getArtifactId(),
|
||||
descriptor.getVersion(), descriptor.isIncludeTransitiveDependencies());
|
||||
descriptor.getVersion(), descriptor.isIncludeTransitiveDependencies(),
|
||||
descriptor.getExcludedDependencies());
|
||||
if (!resolved.isEmpty()) {
|
||||
syncPaths(required, resolved);
|
||||
}
|
||||
|
||||
+20
-6
@@ -18,6 +18,8 @@ package org.jetbrains.jps.model.library;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -29,25 +31,28 @@ public class JpsMavenRepositoryLibraryDescriptor {
|
||||
private final String myArtifactId;
|
||||
private final String myVersion;
|
||||
private final boolean myIncludeTransitiveDependencies;
|
||||
private final List<String> myExcludedDependencies;
|
||||
|
||||
public JpsMavenRepositoryLibraryDescriptor(@NotNull String groupId, @NotNull String artifactId, @NotNull String version) {
|
||||
this(groupId, artifactId, version, true);
|
||||
this(groupId, artifactId, version, true, Collections.emptyList());
|
||||
}
|
||||
|
||||
public JpsMavenRepositoryLibraryDescriptor(@NotNull String groupId, @NotNull String artifactId, @NotNull String version,
|
||||
boolean includeTransitiveDependencies) {
|
||||
boolean includeTransitiveDependencies, @NotNull List<String> excludedDependencies) {
|
||||
myGroupId = groupId;
|
||||
myArtifactId = artifactId;
|
||||
myVersion = version;
|
||||
myIncludeTransitiveDependencies = includeTransitiveDependencies;
|
||||
myExcludedDependencies = excludedDependencies;
|
||||
myMavenId = groupId + ":" + artifactId + ":" + version;
|
||||
}
|
||||
|
||||
public JpsMavenRepositoryLibraryDescriptor(@Nullable String mavenId) {
|
||||
this(mavenId, true);
|
||||
this(mavenId, true, Collections.emptyList());
|
||||
}
|
||||
|
||||
public JpsMavenRepositoryLibraryDescriptor(@Nullable String mavenId, boolean includeTransitiveDependencies) {
|
||||
public JpsMavenRepositoryLibraryDescriptor(@Nullable String mavenId,
|
||||
boolean includeTransitiveDependencies, List<String> excludedDependencies) {
|
||||
myMavenId = mavenId;
|
||||
myIncludeTransitiveDependencies = includeTransitiveDependencies;
|
||||
if (mavenId == null) {
|
||||
@@ -59,6 +64,7 @@ public class JpsMavenRepositoryLibraryDescriptor {
|
||||
myArtifactId = parts.length > 1 ? parts[1] : null;
|
||||
myVersion = parts.length > 2 ? parts[2] : null;
|
||||
}
|
||||
myExcludedDependencies = excludedDependencies;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +84,13 @@ public class JpsMavenRepositoryLibraryDescriptor {
|
||||
return myIncludeTransitiveDependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of excluded transitive dependencies in {@code "<groupId>:<artifactId>"} format.
|
||||
*/
|
||||
public List<String> getExcludedDependencies() {
|
||||
return myExcludedDependencies;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return myVersion;
|
||||
}
|
||||
@@ -88,12 +101,13 @@ public class JpsMavenRepositoryLibraryDescriptor {
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
JpsMavenRepositoryLibraryDescriptor that = (JpsMavenRepositoryLibraryDescriptor)o;
|
||||
return Objects.equals(myMavenId, that.myMavenId) && myIncludeTransitiveDependencies == that.myIncludeTransitiveDependencies;
|
||||
return Objects.equals(myMavenId, that.myMavenId) && myIncludeTransitiveDependencies == that.myIncludeTransitiveDependencies
|
||||
&& myExcludedDependencies.equals(that.myExcludedDependencies);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(myMavenId) * 31 + (myIncludeTransitiveDependencies ? 1 : 0);
|
||||
return myExcludedDependencies.hashCode() * 31 * 31 + Objects.hashCode(myMavenId) * 31 + (myIncludeTransitiveDependencies ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+24
-4
@@ -17,6 +17,7 @@ package org.jetbrains.jps.model.serialization.java;
|
||||
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -387,6 +388,8 @@ public class JpsJavaModelSerializerExtension extends JpsModelSerializerExtension
|
||||
private static class JpsRepositoryLibraryPropertiesSerializer extends JpsLibraryPropertiesSerializer<JpsSimpleElement<JpsMavenRepositoryLibraryDescriptor>> {
|
||||
private static final String MAVEN_ID_ATTRIBUTE = "maven-id";
|
||||
private static final String INCLUDE_TRANSITIVE_DEPS_ATTRIBUTE = "include-transitive-deps";
|
||||
private static final String EXCLUDE_TAG = "exclude";
|
||||
private static final String DEPENDENCY_TAG = "dependency";
|
||||
|
||||
public JpsRepositoryLibraryPropertiesSerializer() {
|
||||
super(JpsRepositoryLibraryType.INSTANCE, JpsRepositoryLibraryType.INSTANCE.getTypeId());
|
||||
@@ -394,10 +397,19 @@ public class JpsJavaModelSerializerExtension extends JpsModelSerializerExtension
|
||||
|
||||
@Override
|
||||
public JpsSimpleElement<JpsMavenRepositoryLibraryDescriptor> loadProperties(@Nullable Element elem) {
|
||||
return JpsElementFactory.getInstance().createSimpleElement(new JpsMavenRepositoryLibraryDescriptor(
|
||||
elem != null ? elem.getAttributeValue(MAVEN_ID_ATTRIBUTE, (String)null) : null,
|
||||
elem == null || Boolean.parseBoolean(elem.getAttributeValue(INCLUDE_TRANSITIVE_DEPS_ATTRIBUTE, "true"))
|
||||
));
|
||||
return JpsElementFactory.getInstance().createSimpleElement(loadDescriptor(elem));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JpsMavenRepositoryLibraryDescriptor loadDescriptor(@Nullable Element elem) {
|
||||
if (elem == null) return new JpsMavenRepositoryLibraryDescriptor(null);
|
||||
|
||||
boolean includeTransitiveDependencies = Boolean.parseBoolean(elem.getAttributeValue(INCLUDE_TRANSITIVE_DEPS_ATTRIBUTE, "true"));
|
||||
Element excludeTag = elem.getChild(EXCLUDE_TAG);
|
||||
List<Element> dependencyTags = excludeTag != null ? excludeTag.getChildren(DEPENDENCY_TAG) : Collections.emptyList();
|
||||
List<String> excludedDependencies = ContainerUtil.map(dependencyTags, it -> it.getAttributeValue(MAVEN_ID_ATTRIBUTE));
|
||||
return new JpsMavenRepositoryLibraryDescriptor(elem.getAttributeValue(MAVEN_ID_ATTRIBUTE, (String)null),
|
||||
includeTransitiveDependencies, excludedDependencies);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -406,6 +418,14 @@ public class JpsJavaModelSerializerExtension extends JpsModelSerializerExtension
|
||||
if (mavenId != null) {
|
||||
element.setAttribute(MAVEN_ID_ATTRIBUTE, mavenId);
|
||||
}
|
||||
List<String> excludedDependencies = properties.getData().getExcludedDependencies();
|
||||
if (!excludedDependencies.isEmpty()) {
|
||||
Element excludeTag = new Element(EXCLUDE_TAG);
|
||||
element.addContent(excludeTag);
|
||||
for (String dependency : excludedDependencies) {
|
||||
excludeTag.addContent(new Element(DEPENDENCY_TAG).setAttribute(MAVEN_ID_ATTRIBUTE, dependency));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<component name="libraryTable">
|
||||
<library name="plain" type="repository">
|
||||
<properties maven-id="junit:junit:3.8.1"/>
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/3.8.1/junit-3.8.1.jar!/"/>
|
||||
</CLASSES>
|
||||
<JAVADOC/>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/3.8.1/junit-3.8.1-sources.jar!/"/>
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
Generated
+15
@@ -0,0 +1,15 @@
|
||||
<component name="libraryTable">
|
||||
<library name="with-excluded-dependencies" type="repository">
|
||||
<properties maven-id="org.apache.httpcomponents:fluent-hc:4.5.5">
|
||||
<exclude>
|
||||
<dependency maven-id="org.apache.httpcomponents:httpclient"/>
|
||||
</exclude>
|
||||
</properties>
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/httpcomponents/fluent-hc/4.5.5/fluent-hc-4.5.5.jar!/"/>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/commons-logging/commons-logging/1.2/commons-logging-1.2.jar!/"/>
|
||||
</CLASSES>
|
||||
<JAVADOC/>
|
||||
<SOURCES/>
|
||||
</library>
|
||||
</component>
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<component name="libraryTable">
|
||||
<library name="without-transitive-dependencies" type="repository">
|
||||
<properties include-transitive-deps="false" maven-id="junit:junit:4.12"/>
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.12/junit-4.12.jar!/"/>
|
||||
</CLASSES>
|
||||
<JAVADOC/>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.12/junit-4.12-sources.jar!/"/>
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.jps.model.serialization;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.model.JpsSimpleElement;
|
||||
import org.jetbrains.jps.model.library.JpsLibrary;
|
||||
import org.jetbrains.jps.model.library.JpsMavenRepositoryLibraryDescriptor;
|
||||
import org.jetbrains.jps.model.library.JpsRepositoryLibraryType;
|
||||
import org.jetbrains.jps.model.library.JpsTypedLibrary;
|
||||
|
||||
public class JpsRepositoryLibrarySerializationTest extends JpsSerializationTestCase {
|
||||
public void testPlain() {
|
||||
JpsMavenRepositoryLibraryDescriptor properties = loadLibrary("plain");
|
||||
assertEquals("junit", properties.getGroupId());
|
||||
assertEquals("junit", properties.getArtifactId());
|
||||
assertEquals("3.8.1", properties.getVersion());
|
||||
assertTrue(properties.isIncludeTransitiveDependencies());
|
||||
assertEmpty(properties.getExcludedDependencies());
|
||||
}
|
||||
|
||||
public void testWithoutTransitiveDependencies() {
|
||||
JpsMavenRepositoryLibraryDescriptor properties = loadLibrary("without-transitive-dependencies");
|
||||
assertFalse(properties.isIncludeTransitiveDependencies());
|
||||
assertEmpty(properties.getExcludedDependencies());
|
||||
}
|
||||
|
||||
public void testWithExcludedDependencies() {
|
||||
JpsMavenRepositoryLibraryDescriptor properties = loadLibrary("with-excluded-dependencies");
|
||||
assertTrue(properties.isIncludeTransitiveDependencies());
|
||||
assertSameElements(properties.getExcludedDependencies(), "org.apache.httpcomponents:httpclient");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JpsMavenRepositoryLibraryDescriptor loadLibrary(String name) {
|
||||
loadProject("/jps/model-serialization/testData/repositoryLibraries");
|
||||
JpsLibrary library = myProject.getLibraryCollection().findLibrary(name);
|
||||
assertNotNull(library);
|
||||
assertSame(JpsRepositoryLibraryType.INSTANCE, library.getType());
|
||||
JpsTypedLibrary<JpsSimpleElement<JpsMavenRepositoryLibraryDescriptor>> typed = library.asTyped(JpsRepositoryLibraryType.INSTANCE);
|
||||
assertNotNull(typed);
|
||||
return typed.getProperties().getData();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user