You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by sd...@apache.org on 2022/05/27 11:17:38 UTC

[netbeans] branch master updated: Initial implementation of Project Dependency API (#4149)

This is an automated email from the ASF dual-hosted git repository.

sdedic pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new ea62da490f Initial implementation of Project Dependency API (#4149)
ea62da490f is described below

commit ea62da490f933d1a4d51abd53dcbf9956035ecaf
Author: Svatopluk Dedic <sv...@oracle.com>
AuthorDate: Fri May 27 13:17:33 2022 +0200

    Initial implementation of Project Dependency API (#4149)
    
    Initial implementation of Project Dependency API
---
 ide/project.dependency/Readme.md                   |  35 ++
 ide/project.dependency/build.xml                   |  25 ++
 ide/project.dependency/manifest.mf                 |   5 +
 .../nbproject/project.properties                   |  21 +-
 ide/project.dependency/nbproject/project.xml       |  66 +++
 .../modules/project/dependency/ArtifactSpec.java   | 188 ++++++++
 .../modules/project/dependency/Bundle.properties   |  22 +-
 .../modules/project/dependency/Dependency.java     |  84 ++++
 .../project/dependency/DependencyResult.java       |  68 +++
 .../project/dependency/ProjectDependencies.java    |  53 +++
 .../dependency/ProjectOperationException.java      |  78 ++++
 .../netbeans/modules/project/dependency/Scope.java |  86 ++++
 .../modules/project/dependency/Scopes.java         |  86 ++++
 .../modules/project/dependency/SourceLocation.java | 105 +++++
 .../spi/ProjectDependenciesImplementation.java     |  46 ++
 java/maven.embedder/nbproject/project.xml          |   3 +
 .../maven/embedder/DependencyTreeFactory.java      |  47 +-
 java/maven/build.xml                               |   7 +
 java/maven/manifest.mf                             |   2 +-
 java/maven/nbproject/project.properties            |   5 +-
 java/maven/nbproject/project.xml                   |  29 ++
 .../queries/MavenDependenciesImplementation.java   | 491 +++++++++++++++++++++
 .../dependencies/golden/testCompileDependencies    |   5 +
 .../dependencies/golden/testRuntimeDependencies    |   7 +
 .../repo/grp/annotation/12.6/_remote.repositories  |   4 +
 .../12.6/annotation-12.6.jar.lastUpdated           |   4 +
 .../annotation-12.6.jardir/META-INF/MANIFEST.MF    |   6 +
 .../maven/nbtest.grp/annotation/pom.properties     |   5 +
 .../META-INF/maven/nbtest.grp/annotation/pom.xml   |  33 ++
 .../repo/grp/annotation/12.6/annotation-12.6.pom   |  33 ++
 .../12.6/annotation-12.6.pom.lastUpdated           |   4 +
 .../repo/grp/annotation/maven-metadata-local.xml   |  12 +
 .../repo/grp/test-lib/12.6/_remote.repositories    |   4 +
 .../12.6/test-lib-12.6.jardir/META-INF/MANIFEST.MF |   6 +
 .../maven/nbtest.grp/test-lib/pom.properties       |   5 +
 .../META-INF/maven/nbtest.grp/test-lib/pom.xml     |  57 +++
 .../repo/grp/test-lib/12.6/test-lib-12.6.pom       |  57 +++
 .../repo/grp/test-lib/maven-metadata-local.xml     |  12 +
 .../repo/grp/test-lib3/12.6/_remote.repositories   |   4 +
 .../test-lib3-12.6.jardir/META-INF/MANIFEST.MF     |   6 +
 .../maven/nbtest.grp/test-lib3/pom.properties      |   5 +
 .../META-INF/maven/nbtest.grp/test-lib3/pom.xml    |  32 ++
 .../repo/grp/test-lib3/12.6/test-lib3-12.6.pom     |  32 ++
 .../repo/grp/test-lib3/maven-metadata-local.xml    |  12 +
 .../repo/grp/test-lib4/12.6/_remote.repositories   |   4 +
 .../test-lib4-12.6.jardir/META-INF/MANIFEST.MF     |   6 +
 .../maven/nbtest.grp/test-lib4/pom.properties      |   5 +
 .../META-INF/maven/nbtest.grp/test-lib4/pom.xml    |  32 ++
 .../repo/grp/test-lib4/12.6/test-lib4-12.6.pom     |  32 ++
 .../repo/grp/test-lib4/maven-metadata-local.xml    |  12 +
 .../grp/test-processor/12.6/_remote.repositories   |   4 +
 .../META-INF/MANIFEST.MF                           |   6 +
 .../maven/nbtest.grp/test-processor/pom.properties |   5 +
 .../maven/nbtest.grp/test-processor/pom.xml        |  45 ++
 .../test-processor/12.6/test-processor-12.6.pom    |  45 ++
 .../grp/test-processor/maven-metadata-local.xml    |  12 +
 .../projects/dependencies/src/annotation/pom.xml   |  33 ++
 .../src/annotation/src/main/java/README            |   1 +
 .../simpleProject/pom-with-processor-broken.xml    |  77 ++++
 .../src/simpleProject/pom-with-processor.xml       |  77 ++++
 .../simpleProject/pom-with-separateProcessors.xml  | 111 +++++
 .../dependencies/src/simpleProject/pom.xml         |  65 +++
 .../src/simpleProject/src/main/java/README         |   1 +
 .../src/simpleProject/src/test/java/README         |   1 +
 .../projects/dependencies/src/test-lib/pom.xml     |  57 +++
 .../dependencies/src/test-lib/src/main/java/README |   1 +
 .../projects/dependencies/src/test-lib3/pom.xml    |  32 ++
 .../src/test-lib3/src/main/java/README             |   1 +
 .../projects/dependencies/src/test-lib4/pom.xml    |  32 ++
 .../src/test-lib4/src/main/java/README             |   1 +
 .../dependencies/src/test-processor/pom.xml        |  45 ++
 .../MavenDependenciesImplementationTest.java       | 257 +++++++++++
 nbbuild/cluster.properties                         |   1 +
 73 files changed, 2852 insertions(+), 46 deletions(-)

diff --git a/ide/project.dependency/Readme.md b/ide/project.dependency/Readme.md
new file mode 100644
index 0000000000..d30bf3b7ed
--- /dev/null
+++ b/ide/project.dependency/Readme.md
@@ -0,0 +1,35 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+# Project Dependencies
+
+This module is highly experimental; provides an abstract API to query project dependncies
+that shall be implemented by
+- gradle
+- maven
+- ant/nbm support
+At this moment, just Maven implements it and I need to validate the API design by adding
+the other implementations before the API is going to be published officially. In the
+meantime, implementation dependencies are required to access / implement the API.
+
+The code will **eventually merge** into `project.api` module and this experimental one
+will be deleted.
+
diff --git a/ide/project.dependency/build.xml b/ide/project.dependency/build.xml
new file mode 100644
index 0000000000..42c863e5c1
--- /dev/null
+++ b/ide/project.dependency/build.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project basedir="." default="netbeans" name="ide/project.dependency">
+    <description>Builds, tests, and runs the project org.netbeans.modules.project.dependency</description>
+    <import file="../../nbbuild/templates/projectized.xml"/>
+</project>
diff --git a/ide/project.dependency/manifest.mf b/ide/project.dependency/manifest.mf
new file mode 100644
index 0000000000..1e11863f62
--- /dev/null
+++ b/ide/project.dependency/manifest.mf
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+AutoUpdate-Show-In-Client: false
+OpenIDE-Module: org.netbeans.modules.project.dependency
+OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/project/dependency/Bundle.properties
+OpenIDE-Module-Implementation-Version: 1
diff --git a/java/maven/nbproject/project.properties b/ide/project.dependency/nbproject/project.properties
similarity index 55%
copy from java/maven/nbproject/project.properties
copy to ide/project.dependency/nbproject/project.properties
index 5a0e448671..b33d05b841 100644
--- a/java/maven/nbproject/project.properties
+++ b/ide/project.dependency/nbproject/project.properties
@@ -15,24 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
+is.autoload=true
 javac.source=1.8
 javac.compilerargs=-Xlint -Xlint:-serial
-cp.extra=${tools.jar}
-javadoc.apichanges=${basedir}/apichanges.xml
-javadoc.arch=${basedir}/arch.xml
-javahelp.hs=maven.hs
-extra.module.files=maven-nblib/
-
-# The CPExtender test fails in library processing (not randomly) since NetBeans 8.2; disabling.
-test.excludes=**/CPExtenderTest.class
-test.config.stableBTD.includes=**/*Test.class
-test.config.stableBTD.excludes=\
-    **/ClassPathProviderImplTest.class,\
-    **/CPExtenderTest.class,\
-    **/JavaOutputListenerProviderTest.class,\
-    **/ProjectOpenedHookImplTest.class
-
-jnlp.indirect.files=maven-nblib/netbeans-eventspy.jar,maven-nblib/netbeans-cos.jar
-
-# requires nb.javac for compiling of tests
-requires.nb.javac=true
\ No newline at end of file
+spec.version.base=1.0.0
diff --git a/ide/project.dependency/nbproject/project.xml b/ide/project.dependency/nbproject/project.xml
new file mode 100644
index 0000000000..c26553a435
--- /dev/null
+++ b/ide/project.dependency/nbproject/project.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>org.netbeans.modules.project.dependency</code-name-base>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>org.netbeans.api.annotations.common</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.45</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.87</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.29</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.51</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>
diff --git a/ide/project.dependency/src/org/netbeans/modules/project/dependency/ArtifactSpec.java b/ide/project.dependency/src/org/netbeans/modules/project/dependency/ArtifactSpec.java
new file mode 100644
index 0000000000..8f6ff7e53e
--- /dev/null
+++ b/ide/project.dependency/src/org/netbeans/modules/project/dependency/ArtifactSpec.java
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.project.dependency;
+
+import java.util.Objects;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.annotations.common.NullAllowed;
+
+/**
+ * Represents an artifact. Each artifact is identified by
+ * <ul>
+ * <li>group or organization id
+ * <li>artifact id
+ * <li>version
+ * <li>(optional) classifier; no classifier shall be interpreted as a
+ * regular build artifact
+ * <li>(optional) type; not type shall be interepreted as the default type
+ * for the processing compiler or builder
+ * </ul>
+ * The version specified is further classified by {@link VersionKind}, to 
+ * distinguish versions possibly from repositories, development versions and
+ * floating versions.
+ * 
+ * @author sdedic
+ */
+public final class ArtifactSpec<T> {
+    /**
+     * Kind of the artifact version
+     */
+    public enum VersionKind {
+        /**
+         * Regular publishable artifact
+         */
+        REGULAR, 
+        
+        /**
+         * Snapshot artifact
+         */
+        SNAPSHOT
+    };
+    
+    private final VersionKind kind;
+    private final String type;
+    private final String groupId;
+    private final String artifactId;
+    private final String versionSpec;
+    private final String classifier;
+    private final boolean optional;
+    final T data;
+
+    ArtifactSpec(VersionKind kind, String groupId, String artifactId, String versionSpec, String type, String classifier, boolean optional, T impl) {
+        this.kind = kind;
+        this.groupId = groupId;
+        this.artifactId = artifactId;
+        this.versionSpec = versionSpec;
+        this.classifier = classifier;
+        this.optional = optional;
+        this.data = impl;
+        this.type = type;
+    }
+
+    public VersionKind getKind() {
+        return kind;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public String getGroupId() {
+        return groupId;
+    }
+
+    public String getArtifactId() {
+        return artifactId;
+    }
+
+    public String getVersionSpec() {
+        return versionSpec;
+    }
+
+    public String getClassifier() {
+        return classifier;
+    }
+
+    public boolean isOptional() {
+        return optional;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 7;
+        hash = 79 * hash + Objects.hashCode(this.kind);
+        hash = 79 * hash + Objects.hashCode(this.type);
+        hash = 79 * hash + Objects.hashCode(this.groupId);
+        hash = 79 * hash + Objects.hashCode(this.artifactId);
+        hash = 79 * hash + Objects.hashCode(this.versionSpec);
+        hash = 79 * hash + Objects.hashCode(this.classifier);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final ArtifactSpec<?> other = (ArtifactSpec<?>) obj;
+        if (!Objects.equals(this.type, other.type)) {
+            return false;
+        }
+        if (!Objects.equals(this.groupId, other.groupId)) {
+            return false;
+        }
+        if (!Objects.equals(this.artifactId, other.artifactId)) {
+            return false;
+        }
+        if (!Objects.equals(this.versionSpec, other.versionSpec)) {
+            return false;
+        }
+        if (!Objects.equals(this.classifier, other.classifier)) {
+            return false;
+        }
+        return this.kind == other.kind;
+    }
+    
+    public String toString() {
+        StringBuilder sb = new StringBuilder(
+            String.format("%s:%s:%s", getGroupId(), getArtifactId(), getVersionSpec() == null ? "" : getVersionSpec())
+        );
+        if (classifier != null) {
+            sb.append(":").append(classifier);
+        }
+        if (type != null) {
+            sb.append("[").append(type).append("]");
+        }
+        if (optional) {
+            sb.append("?");
+        }
+        return sb.toString();
+    }
+    
+    /**
+     * Returns opaque project-specific data. If searching for
+     * a project-specific extension, use {@link ProjectDependencies#findAdapters} instead.
+     * 
+     * @return unspecified underlying project data
+     */
+    public T getProjectData() {
+        return data;
+    }
+    
+    public static <V> ArtifactSpec<V> createVersionSpec(
+            @NonNull String groupId, @NonNull String artifactId, 
+            @NullAllowed String type, @NullAllowed String classifier, 
+            @NonNull String versionSpec, boolean optional, @NonNull V data) {
+        return new ArtifactSpec<V>(VersionKind.REGULAR, groupId, artifactId, versionSpec, type, classifier, optional, data);
+    }
+
+    public static <V> ArtifactSpec<V> createSnapshotSpec(
+            @NonNull String groupId, @NonNull String artifactId, 
+            @NullAllowed String type, @NullAllowed String classifier, 
+            @NonNull String versionSpec, boolean optional, @NonNull V data) {
+        return new ArtifactSpec<V>(VersionKind.SNAPSHOT, groupId, artifactId, versionSpec, type, classifier, false, data);
+    }
+
+}
diff --git a/java/maven/nbproject/project.properties b/ide/project.dependency/src/org/netbeans/modules/project/dependency/Bundle.properties
similarity index 51%
copy from java/maven/nbproject/project.properties
copy to ide/project.dependency/src/org/netbeans/modules/project/dependency/Bundle.properties
index 5a0e448671..06481c66c1 100644
--- a/java/maven/nbproject/project.properties
+++ b/ide/project.dependency/src/org/netbeans/modules/project/dependency/Bundle.properties
@@ -15,24 +15,4 @@
 # specific language governing permissions and limitations
 # under the License.
 
-javac.source=1.8
-javac.compilerargs=-Xlint -Xlint:-serial
-cp.extra=${tools.jar}
-javadoc.apichanges=${basedir}/apichanges.xml
-javadoc.arch=${basedir}/arch.xml
-javahelp.hs=maven.hs
-extra.module.files=maven-nblib/
-
-# The CPExtender test fails in library processing (not randomly) since NetBeans 8.2; disabling.
-test.excludes=**/CPExtenderTest.class
-test.config.stableBTD.includes=**/*Test.class
-test.config.stableBTD.excludes=\
-    **/ClassPathProviderImplTest.class,\
-    **/CPExtenderTest.class,\
-    **/JavaOutputListenerProviderTest.class,\
-    **/ProjectOpenedHookImplTest.class
-
-jnlp.indirect.files=maven-nblib/netbeans-eventspy.jar,maven-nblib/netbeans-cos.jar
-
-# requires nb.javac for compiling of tests
-requires.nb.javac=true
\ No newline at end of file
+OpenIDE-Module-Name=Project Dependencies
diff --git a/ide/project.dependency/src/org/netbeans/modules/project/dependency/Dependency.java b/ide/project.dependency/src/org/netbeans/modules/project/dependency/Dependency.java
new file mode 100644
index 0000000000..7c726d6c77
--- /dev/null
+++ b/ide/project.dependency/src/org/netbeans/modules/project/dependency/Dependency.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.project.dependency;
+
+import java.util.List;
+
+/**
+ * Represents a dependency of an artifact. The {@link #getChildren()} artifacts are
+ * needed in a certain {@link #getScope()}; should be ignored in unrelated scopes.
+ * The artifact that is subject of this dependency is the {@link #getArtifact()}.
+ * Children are expressed using other {@link Dependency} instances.
+ * <p>
+ * Dependency does not have well-defined {@link #equals} and {@link #hashCode}, use
+ * {@link #getArtifact()} as key in Maps.
+ * 
+ * @author sdedic
+ */
+public final class Dependency {
+    private final ArtifactSpec  artifact;
+    private final List<Dependency> children;
+    private final Scope scope;
+    final Object data;
+
+    Dependency(ArtifactSpec artifact, List<Dependency> children, Scope scope, Object data) {
+        this.artifact = artifact;
+        this.children = children;
+        this.scope = scope;
+        this.data = data;
+    }
+
+    public ArtifactSpec getArtifact() {
+        return artifact;
+    }
+
+    public List<Dependency> getChildren() {
+        return children;
+    }
+
+    public Scope getScope() {
+        return scope;
+    }
+    
+    public Object getProjectData() {
+        return data;
+    }
+    
+    public String toString() {
+        return getArtifact() + "[" + scope + "]";
+    }
+    
+    public static Dependency create(ArtifactSpec artifact, Scope scope, List<Dependency> children, Object data) {
+        return new Dependency(artifact, children, scope, data);
+    }
+    
+    /**
+     * Allows to filter artifacts and their dependency subtrees.
+     */
+    public interface Filter {
+        /**
+         * Decide if the artifact 'a' and its dependencies should be included in the report.
+         * @param s the scope which requires dependency on "a"
+         * @param a the artifact
+         * @return true, if "a" should be included in the result; false to exclude it and its
+         * dependencies.
+         */
+        public boolean accept(Scope s, ArtifactSpec a);
+    }
+}
diff --git a/ide/project.dependency/src/org/netbeans/modules/project/dependency/DependencyResult.java b/ide/project.dependency/src/org/netbeans/modules/project/dependency/DependencyResult.java
new file mode 100644
index 0000000000..9442f42ad9
--- /dev/null
+++ b/ide/project.dependency/src/org/netbeans/modules/project/dependency/DependencyResult.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.project.dependency;
+
+import java.io.IOException;
+import javax.swing.event.ChangeListener;
+import org.netbeans.api.project.Project;
+import org.openide.util.Lookup;
+
+/**
+ * Results of a dependency inspection. Contains dependency graph from the {@link #getRoot}.
+ * The result may become invalid, as a result of project changes or dependency changes.
+ * The state change will be reported by {@link ChangeListener}. If the client is interested
+ * in an updated result, it must perform another dependency scan. Once invalid instance
+ * will never turn back to valid.
+ * <p>
+ * The {@link #getLookup() lookup} can be used to search for project-specific services that
+ * can provide further info on the artifacts or dependencies.
+ * @author sdedic
+ */
+public interface DependencyResult extends Lookup.Provider {
+    /**
+     * @return the inspected project
+     */
+    public Project getProject();
+    /**
+     * The root of the dependency tree. Its artifact should represent the project itself.
+     * @return project dependency root.
+     */
+    public Dependency getRoot();
+    
+    public boolean isValid();
+    
+    /**
+     * Registers a Listener to be notified when validity changes.
+     * @param l listener
+     */
+    public void addChangeListener(ChangeListener l);
+
+    /**
+     * Unregisters a previously registered Listener.
+     * @param l listener
+     */
+    public void removeChangeListener(ChangeListener l);
+
+    /**
+     * Attempts to find location where this dependency is declared.
+     * @param d
+     * @return 
+     */
+    public SourceLocation getDeclarationRange(Dependency d) throws IOException;
+}
diff --git a/ide/project.dependency/src/org/netbeans/modules/project/dependency/ProjectDependencies.java b/ide/project.dependency/src/org/netbeans/modules/project/dependency/ProjectDependencies.java
new file mode 100644
index 0000000000..633c9aa8e0
--- /dev/null
+++ b/ide/project.dependency/src/org/netbeans/modules/project/dependency/ProjectDependencies.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.project.dependency;
+
+import java.util.Arrays;
+import java.util.Collections;
+import org.netbeans.api.project.Project;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+import org.netbeans.modules.project.dependency.spi.ProjectDependenciesImplementation;
+import org.openide.filesystems.FileObject;
+
+/**
+ * Project Query that collects dependencies using project-specific services.
+ * @author sdedic
+ */
+public class ProjectDependencies {
+    
+    public static ArtifactSpec getProjectArtifact(Project target) {
+        ProjectDependenciesImplementation pds = target.getLookup().lookup(ProjectDependenciesImplementation.class);
+        if (pds == null) {
+            return null;
+        }
+        return pds.getProjectArtifact();
+    }
+    
+    public static DependencyResult findDependencies(Project target, Dependency.Filter filterOrNull, Scope... scopes) throws ProjectOperationException {
+        ProjectDependenciesImplementation pds = target.getLookup().lookup(ProjectDependenciesImplementation.class);
+        if (pds == null) {
+            return null;
+        } else {
+            return pds.findDependencies(
+                    scopes == null ? Collections.singletonList(Scopes.COMPILE) : Arrays.asList(scopes), 
+                    filterOrNull != null ? filterOrNull : (s, a) -> true);
+        }
+    }
+}
diff --git a/ide/project.dependency/src/org/netbeans/modules/project/dependency/ProjectOperationException.java b/ide/project.dependency/src/org/netbeans/modules/project/dependency/ProjectOperationException.java
new file mode 100644
index 0000000000..fce436c492
--- /dev/null
+++ b/ide/project.dependency/src/org/netbeans/modules/project/dependency/ProjectOperationException.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.project.dependency;
+
+import org.netbeans.api.project.Project;
+
+/**
+ * The exception is thrown when an error happens during project operation because
+ * of limited or refused access to the project metadata / structure.
+ * <p/>
+ * It may wrap underlying build system error, such as maven not able to parse the
+ * POM.
+ * @author sdedic
+ */
+public final class ProjectOperationException extends IllegalStateException {
+    public enum State {
+        /**
+         * The project has not been yet fully initialized. The query can not
+         * produce sane results.
+         */
+        UNINITIALIZED,
+        
+        /**
+         * The project definition is broken so that the query cannot be evaluated.
+         */
+        BROKEN,
+        
+        /**
+         * Online resources are required to evaluate the query, but the query was not
+         * allowed to inspect them.
+         */
+        OFFLINE,
+        
+        /**
+         * The project is OK
+         */
+        OK,
+    }
+    
+    private final Project project;
+    private final State state;
+
+    public ProjectOperationException(Project project, State state, String s) {
+        super(s);
+        this.project = project;
+        this.state = state;
+    }
+
+    public ProjectOperationException(Project project, State state, String message, Throwable cause) {
+        super(message, cause);
+        this.state = state;
+        this.project = project;
+    }
+
+    public Project getProject() {
+        return project;
+    }
+
+    public State getState() {
+        return state;
+    }
+}
diff --git a/ide/project.dependency/src/org/netbeans/modules/project/dependency/Scope.java b/ide/project.dependency/src/org/netbeans/modules/project/dependency/Scope.java
new file mode 100644
index 0000000000..1e2a78c75a
--- /dev/null
+++ b/ide/project.dependency/src/org/netbeans/modules/project/dependency/Scope.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.project.dependency;
+
+import java.util.Objects;
+
+/**
+ * Represents "scope" (maven term) or "configuration" (gradle term). Eeach project type
+ * may define multiple additional Scopes, but should support the abstract ones defined in
+ * {@link Scopes}. 
+ * <p/>
+ * Scopes are identified by its {@link #name name}; two scopes with the same name are equal.
+ * Project implementations may provide their own scopes with standard names since they
+ * may use different include/imply hierarchy.
+ * 
+ * @author sdedic
+ */
+public abstract class Scope {
+    private final String name;
+
+    protected Scope(String name) {
+        this.name = name;
+    }
+    
+    /**
+     * Checks if this scope includes the other one. If yes, then queries that executed for this scope
+     * should return all results from the included scope.
+     * 
+     * @param s scope to test
+     * @return true, if data for scope "s" are included by this scope; false otherwise (i.e. unrelated scopes)
+     */
+    public abstract boolean includes(Scope s);
+    
+    /**
+     * Checks if this scope exports the other scope. A scope may {@link #includes include} other
+     * scope, but can choose not to propagate its contents further.
+     * @param s the scope to test
+     * @return true, if data for scope "s" are exported by this scope; false otherwise (i.e. unrelated scopes)
+     */
+    public abstract boolean exports(Scope s);
+    
+    /**
+     * @return name / identifier for the scope. Not subject to L10N.
+     */
+    public String name() {
+        return name;
+    }
+
+    @Override
+    public final int hashCode() {
+        int hash = 5;
+        hash = 67 * hash + Objects.hashCode(this.name);
+        return hash;
+    }
+
+    @Override
+    public final boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final Scope other = (Scope) obj;
+        return Objects.equals(this.name, other.name);
+    }
+}
diff --git a/ide/project.dependency/src/org/netbeans/modules/project/dependency/Scopes.java b/ide/project.dependency/src/org/netbeans/modules/project/dependency/Scopes.java
new file mode 100644
index 0000000000..3672ba64d7
--- /dev/null
+++ b/ide/project.dependency/src/org/netbeans/modules/project/dependency/Scopes.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.project.dependency;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ *
+ * @author sdedic
+ */
+public final class Scopes {
+    /**
+     * Build process dependencies. Annotation processors, buildtime tools, code generators.
+     */
+    public static final Scope PROCESS = new DefaultScope("compileProcessing", Collections.emptySet(), Collections.emptySet());
+
+    /**
+     * External dependencies, not distributed with the application, but provided by the environment
+     */
+    public static final Scope EXTERNAL = new DefaultScope("external", Collections.emptySet(), Collections.emptySet());
+    
+    /**
+     * Test dependencies.
+     */
+    public static final Scope TEST = new DefaultScope("test", Collections.emptySet(), Collections.emptySet());
+    
+    /**
+     * Compile dependencies. Resources used by build tools to build the application. Includes 
+     * {@link #PROCESS} but does not export it further.
+     */
+    public static final Scope COMPILE = new DefaultScope("compilation", 
+            Collections.singleton(PROCESS), Collections.singleton(PROCESS));
+    
+    /**
+     * Runtime dependencies. Includes compile dependencies.
+     */
+    public static final Scope RUNTIME = new DefaultScope("runtime", Collections.singleton(COMPILE), Collections.emptySet());
+    
+    /**
+     * Included resources.
+    public static final Scope INCLUDED = new DefaultScope("included", Collections.emptySet(), Collections.emptySet());
+     */
+    
+    static final class DefaultScope extends Scope {
+        private final Set<Scope> includes;
+        private final Set<Scope> stops;
+
+        public DefaultScope(String name, Set<Scope> includes, Set<Scope> stops) {
+            super(name);
+            this.includes = includes;
+            this.stops = stops;
+        }
+
+        @Override
+        public boolean includes(Scope s) {
+            return s == this || includes.contains(s);
+        }
+
+        @Override
+        public boolean exports(Scope s) {
+            return s == this || (!stops.contains(s) && includes(s));
+        }
+
+        @Override
+        public String toString() {
+            return name();
+        }
+    }
+}
diff --git a/ide/project.dependency/src/org/netbeans/modules/project/dependency/SourceLocation.java b/ide/project.dependency/src/org/netbeans/modules/project/dependency/SourceLocation.java
new file mode 100644
index 0000000000..00a457ff18
--- /dev/null
+++ b/ide/project.dependency/src/org/netbeans/modules/project/dependency/SourceLocation.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.project.dependency;
+
+import org.openide.filesystems.FileObject;
+
+/**
+ * Represents a location range in a project file occupied by a project model object.
+ * In case the range cannot be determined,
+ * the start an end position are equal. In the case the position cannot be determined
+ * at all, the start (and end) positions are set to -1.
+ * <p/>
+ * In the case the object itself is not present in the project file, but is implied
+ * by another project construction, the {@link #getImpliedBy()} is not null, and provides
+ * the model for that construction. For example a dependency may be introduced by an intermediate
+ * libraries. In that case, when the API is queried for the dependency declaration source,
+ * it will return the direct dependence that introduced the dependency in question from {@link #getImpliedBy}
+ * and its location range.
+ * 
+ * @author sdedic
+ */
+public final class SourceLocation {
+    private final FileObject file;
+    private final int startOffset;
+    private final int endOffset;
+    private final Object impliedBy;
+
+    public SourceLocation(FileObject file, int startOffset, int endOffset, Object impliedBy) {
+        this.file = file;
+        this.startOffset = startOffset;
+        this.endOffset = endOffset;
+        this.impliedBy = impliedBy;
+    }
+
+    /**
+     * @return Returns the file.
+     */
+    public FileObject getFile() {
+        return file;
+    }
+
+    /**
+     * Returns starting offset of the construct in the project file. May return -1,
+     * if the position can not be determined.
+     * @return startinf offset or -1
+     */
+    public int getStartOffset() {
+        return startOffset;
+    }
+
+    /**
+     * Ending offset of the project construct in the project file, exclusive. May return
+     * the same value as {@link #getStartOffset} if the range can not be determined. Will return
+     * -1 if {@link #getStartOffset()} is -1.
+     * @return ending offset, inclusive, or -1.
+     */
+    public int getEndOffset() {
+        return endOffset;
+    }
+
+    /**
+     * Determines if the construct is directly in the project source, or implied by some
+     * other construction. If this method returns {@code null}, the queried project construct
+     * is specified in the project file, and {@link #getStartOffset()} / {@link #getEndOffset()}
+     * give its location or range. If the return value is non-{@code null}, it represents
+     * a project element / metadata that caused the queried project construct into existence.
+     * Start and end offset apply to that "owning" construct instead.
+     * 
+     * @return null if the Location is occupied by the queried construct directly, or
+     * the project element that impled the queried construct.
+     */
+    public Object getImpliedBy() {
+        return impliedBy;
+    }
+    
+    /**
+     * @return true, if the offset within the file is known
+     */
+    public boolean hasPosition() {
+        return startOffset > -1;
+    }
+    
+    /**
+     * @return false, if the Location represents a non-empty range.
+     */
+    public boolean isEmpty() {
+        return startOffset >= endOffset;
+    }
+}
diff --git a/ide/project.dependency/src/org/netbeans/modules/project/dependency/spi/ProjectDependenciesImplementation.java b/ide/project.dependency/src/org/netbeans/modules/project/dependency/spi/ProjectDependenciesImplementation.java
new file mode 100644
index 0000000000..6adc3ddd67
--- /dev/null
+++ b/ide/project.dependency/src/org/netbeans/modules/project/dependency/spi/ProjectDependenciesImplementation.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.project.dependency.spi;
+
+import java.util.Collection;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.annotations.common.NullAllowed;
+import org.netbeans.modules.project.dependency.ArtifactSpec;
+import org.netbeans.modules.project.dependency.Dependency;
+import org.netbeans.modules.project.dependency.DependencyResult;
+import org.netbeans.modules.project.dependency.ProjectOperationException;
+import org.netbeans.modules.project.dependency.Scope;
+
+/**
+ *
+ * @author sdedic
+ */
+public interface ProjectDependenciesImplementation {
+    @NonNull
+    public ArtifactSpec getProjectArtifact();
+    
+    @NonNull
+    public DependencyResult findDependencies(
+            @NullAllowed Collection<Scope> scopes, @NullAllowed Dependency.Filter filter)
+            throws ProjectOperationException;
+    /*
+    @CheckForNull
+    public Dependency mergeDependencies(@NonNull Dependency one, @NonNull Dependency two);
+    */
+}
diff --git a/java/maven.embedder/nbproject/project.xml b/java/maven.embedder/nbproject/project.xml
index c3856b25b7..cb0f0d67c1 100644
--- a/java/maven.embedder/nbproject/project.xml
+++ b/java/maven.embedder/nbproject/project.xml
@@ -225,6 +225,9 @@
                 <package>org.apache.maven.settings.io.xpp3</package>
                 <package>org.apache.maven.shared.dependency.tree</package>
                 <package>org.apache.maven.shared.dependency.tree.traversal</package>
+                <package>org.apache.maven.shared.dependency.graph</package>
+                <package>org.apache.maven.shared.dependency.graph.filter</package>
+                <package>org.apache.maven.shared.dependency.graph.traversal</package>
                 <package>org.apache.maven.wagon</package>
                 <package>org.apache.maven.wagon.authentication</package>
                 <package>org.apache.maven.wagon.authorization</package>
diff --git a/java/maven.embedder/src/org/netbeans/modules/maven/embedder/DependencyTreeFactory.java b/java/maven.embedder/src/org/netbeans/modules/maven/embedder/DependencyTreeFactory.java
index 54b4e4dfae..e8891456e6 100644
--- a/java/maven.embedder/src/org/netbeans/modules/maven/embedder/DependencyTreeFactory.java
+++ b/java/maven.embedder/src/org/netbeans/modules/maven/embedder/DependencyTreeFactory.java
@@ -18,23 +18,36 @@
  */
 package org.netbeans.modules.maven.embedder;
 
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.maven.DefaultMaven;
+import org.apache.maven.Maven;
 import org.apache.maven.artifact.factory.ArtifactFactory;
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
 import org.apache.maven.artifact.repository.ArtifactRepository;
 import org.apache.maven.artifact.resolver.ArtifactCollector;
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.model.building.ModelBuildingRequest;
 import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.ProjectBuildingRequest;
+import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
+import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
+import org.apache.maven.shared.dependency.graph.internal.DefaultDependencyGraphBuilder;
 import org.apache.maven.shared.dependency.tree.DependencyNode;
 import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder;
 import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.openide.util.Exceptions;
 
 /**
  *
  * @author mkleint
  */
 public class DependencyTreeFactory {
-
+    private static final Logger LOG = Logger.getLogger(DependencyTreeFactory.class.getName());
+    
     public static DependencyNode createDependencyTree(MavenProject project, MavenEmbedder embedder, String scope) {
         
         //TODO: check alternative for deprecated maven components 
@@ -51,10 +64,35 @@ public class DependencyTreeFactory {
         assert collector !=null : "ArtifactCollector component not found in maven";
 
         embedder.setUpLegacySupport();
-       
+        
         return createDependencyTree(project, builder, embedder.getLocalRepository(), factory, source, collector, scope);
 
     }
+    
+    public static org.apache.maven.shared.dependency.graph.DependencyNode createDependencyGraph(MavenProject project, MavenEmbedder embedder, String scope) {
+        ArtifactFilter artifactFilter = createResolvingArtifactFilter(scope);
+        MavenExecutionRequest req = embedder.createMavenExecutionRequest();
+        req.setPom(project.getFile());
+        req.setOffline(true);
+        
+        ProjectBuildingRequest configuration = req.getProjectBuildingRequest();
+        configuration.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
+        configuration.setResolveDependencies(true);
+        
+        DependencyGraphBuilder depBuilder = embedder.lookupComponent(DependencyGraphBuilder.class);
+        org.apache.maven.shared.dependency.graph.DependencyNode graphNode;
+        try {
+            DefaultMaven maven = (DefaultMaven)embedder.getPlexus().lookup(Maven.class);
+            configuration.setRepositorySession(maven.newRepositorySession(req));
+            MavenProject copy = project.clone();
+            copy.setProjectBuildingRequest(configuration);
+            graphNode = depBuilder.buildDependencyGraph(copy, artifactFilter);
+            return graphNode;
+        } catch (ComponentLookupException | DependencyGraphBuilderException ex) {
+            LOG.log(Level.INFO, "Dependency tree scan failed", ex);
+            return null;
+        }
+    }
 
 
     //copied from dependency:tree mojo
@@ -64,15 +102,16 @@ public class DependencyTreeFactory {
             ArtifactCollector artifactCollector,
             String scope) {
         ArtifactFilter artifactFilter = createResolvingArtifactFilter(scope);
-
+        
         try {
             // TODO: note that filter does not get applied due to MNG-3236
             return dependencyTreeBuilder.buildDependencyTree(project,
                     localRepository, artifactFactory,
                     artifactMetadataSource, artifactFilter, artifactCollector);
         } catch (DependencyTreeBuilderException exception) {
+            LOG.log(Level.INFO, "Dependency tree scan failed", exception);
+            return null;
         }
-        return null;
     }
 
     //copied from dependency:tree mojo
diff --git a/java/maven/build.xml b/java/maven/build.xml
index c05f9ce7bb..7053dba79a 100644
--- a/java/maven/build.xml
+++ b/java/maven/build.xml
@@ -87,6 +87,13 @@
          <package-artifact-from-dir jarbasename="test-lib3-12.6" relpath="projects/processors/repo/grp/test-lib3/12.6"/>
          <package-artifact-from-dir jarbasename="test-lib4-12.6" relpath="projects/processors/repo/grp/test-lib4/12.6"/>
          <package-artifact-from-dir jarbasename="test-processor-12.6" relpath="projects/processors/repo/grp/test-processor/12.6"/>
+
+         <package-artifact-from-dir jarbasename="annotation-12.6" relpath="projects/dependencies/repo/grp/annotation/12.6"/>
+         <package-artifact-from-dir jarbasename="test-lib-12.6" relpath="projects/dependencies/repo/grp/test-lib/12.6"/>
+         <package-artifact-from-dir jarbasename="test-lib3-12.6" relpath="projects/dependencies/repo/grp/test-lib3/12.6"/>
+         <package-artifact-from-dir jarbasename="test-lib4-12.6" relpath="projects/dependencies/repo/grp/test-lib4/12.6"/>
+         <package-artifact-from-dir jarbasename="test-processor-12.6" relpath="projects/dependencies/repo/grp/test-processor/12.6"/>
+
     </target>
 
 </project>
diff --git a/java/maven/manifest.mf b/java/maven/manifest.mf
index 0200e6720c..2ee0fa6162 100644
--- a/java/maven/manifest.mf
+++ b/java/maven/manifest.mf
@@ -1,6 +1,6 @@
 Manifest-Version: 1.0
 OpenIDE-Module: org.netbeans.modules.maven/2
-OpenIDE-Module-Specification-Version: 2.154
+OpenIDE-Module-Implementation-Version: 1
 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/maven/Bundle.properties
 OpenIDE-Module-Layer: org/netbeans/modules/maven/layer.xml
 AutoUpdate-Show-In-Client: false
diff --git a/java/maven/nbproject/project.properties b/java/maven/nbproject/project.properties
index 5a0e448671..d787680274 100644
--- a/java/maven/nbproject/project.properties
+++ b/java/maven/nbproject/project.properties
@@ -22,6 +22,7 @@ javadoc.apichanges=${basedir}/apichanges.xml
 javadoc.arch=${basedir}/arch.xml
 javahelp.hs=maven.hs
 extra.module.files=maven-nblib/
+spec.version.base: 2.154
 
 # The CPExtender test fails in library processing (not randomly) since NetBeans 8.2; disabling.
 test.excludes=**/CPExtenderTest.class
@@ -35,4 +36,6 @@ test.config.stableBTD.excludes=\
 jnlp.indirect.files=maven-nblib/netbeans-eventspy.jar,maven-nblib/netbeans-cos.jar
 
 # requires nb.javac for compiling of tests
-requires.nb.javac=true
\ No newline at end of file
+requires.nb.javac=true
+
+test-unit-sys-prop.test.netbeans.dest.dir=${netbeans.dest.dir}
\ No newline at end of file
diff --git a/java/maven/nbproject/project.xml b/java/maven/nbproject/project.xml
index ea54c34796..4c913e2679 100644
--- a/java/maven/nbproject/project.xml
+++ b/java/maven/nbproject/project.xml
@@ -116,6 +116,14 @@
                         <specification-version>1.35</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.editor.document</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.26</specification-version>
+                    </run-dependency>
+                </dependency>
                 <dependency>
                     <code-name-base>org.netbeans.modules.editor.indent.project</code-name-base>
                     <build-prerequisite/>
@@ -509,6 +517,14 @@
                         <specification-version>6.64</specification-version>
                     </run-dependency>
                 </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.project.dependency</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <implementation-version/>
+                    </run-dependency>
+                </dependency>
             </module-dependencies>
             <test-dependencies>
                 <test-type>
@@ -576,6 +592,19 @@
                     <test-dependency>
                         <code-name-base>org.netbeans.libs.freemarker</code-name-base>
                     </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.modules.xml.text</code-name-base>
+                        <recursive/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.modules.editor.mimelookup.impl</code-name-base>
+                        <recursive/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.openide.modules</code-name-base>
+                        <compile-dependency/>
+                        <test/>
+                    </test-dependency>
                 </test-type>
             </test-dependencies>
             <friend-packages>
diff --git a/java/maven/src/org/netbeans/modules/maven/queries/MavenDependenciesImplementation.java b/java/maven/src/org/netbeans/modules/maven/queries/MavenDependenciesImplementation.java
new file mode 100644
index 0000000000..ac1bcfbad2
--- /dev/null
+++ b/java/maven/src/org/netbeans/modules/maven/queries/MavenDependenciesImplementation.java
@@ -0,0 +1,491 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.maven.queries;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.StyledDocument;
+import org.apache.maven.DefaultMaven;
+import org.apache.maven.Maven;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
+import org.apache.maven.artifact.resolver.filter.CumulativeScopeArtifactFilter;
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.model.InputLocation;
+import org.apache.maven.model.InputSource;
+import org.apache.maven.model.Model;
+import org.apache.maven.model.building.ModelBuildingException;
+import org.apache.maven.model.building.ModelBuildingRequest;
+import org.apache.maven.model.building.ModelBuildingResult;
+import org.apache.maven.project.DependencyResolutionException;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.ProjectBuildingRequest;
+import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
+import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
+import org.apache.maven.shared.dependency.graph.DependencyNode;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.netbeans.api.editor.document.LineDocument;
+import org.netbeans.api.editor.document.LineDocumentUtils;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.maven.api.NbMavenProject;
+import org.netbeans.modules.maven.embedder.EmbedderFactory;
+import org.netbeans.modules.maven.embedder.MavenEmbedder;
+import org.netbeans.modules.project.dependency.ArtifactSpec;
+import org.netbeans.modules.project.dependency.Dependency;
+import org.netbeans.modules.project.dependency.DependencyResult;
+import org.netbeans.modules.project.dependency.ProjectOperationException;
+import org.netbeans.modules.project.dependency.Scope;
+import org.netbeans.modules.project.dependency.Scopes;
+import org.netbeans.modules.project.dependency.SourceLocation;
+import org.netbeans.modules.project.dependency.spi.ProjectDependenciesImplementation;
+import org.netbeans.spi.project.ProjectServiceProvider;
+import org.openide.cookies.EditorCookie;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.loaders.DataObject;
+import org.openide.util.Exceptions;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle;
+import org.openide.util.WeakListeners;
+
+/**
+ *
+ * @author sdedic
+ */
+@ProjectServiceProvider(service = ProjectDependenciesImplementation.class, projectType="org-netbeans-modules-maven")
+public class MavenDependenciesImplementation implements ProjectDependenciesImplementation {
+    private final Project project;
+    private NbMavenProject nbMavenProject;
+    
+    private static final Set<Scope> SCOPES = new HashSet<>();
+    
+    static {
+        SCOPES.add(Scopes.COMPILE);
+        SCOPES.add(Scopes.RUNTIME);
+        SCOPES.add(Scopes.EXTERNAL);
+        SCOPES.add(Scopes.TEST);
+    }
+    
+    public MavenDependenciesImplementation(Project project) {
+        this.project = project;
+    }
+    
+    private void init() {
+        synchronized (this) {
+            if (nbMavenProject != null) {
+                return;
+            }
+            nbMavenProject = project.getLookup().lookup(NbMavenProject.class);
+        }
+    }
+    
+    static final Map<Scope, String> mavenScopes;
+    
+    static {
+        mavenScopes = new HashMap<>();
+        mavenScopes.put(Scopes.PROCESS, "compile");
+        mavenScopes.put(Scopes.COMPILE, "compile");
+        mavenScopes.put(Scopes.RUNTIME, "runtime");
+        mavenScopes.put(Scopes.TEST, "test");
+        mavenScopes.put(Scopes.EXTERNAL, "provided");
+    }
+    
+    static String mavenScope(Scope s) {
+        return mavenScopes.getOrDefault(s, "runtime");
+    }
+    
+    @Override
+    public ArtifactSpec getProjectArtifact() {
+        init();
+        Artifact a = nbMavenProject.getMavenProject().getArtifact();
+        if (a.isSnapshot()) {
+            return ArtifactSpec.createSnapshotSpec(a.getGroupId(), a.getArtifactId(), 
+                    a.getType(), a.getClassifier(), a.getVersion(), a.isOptional(), a);
+        } else {
+            return ArtifactSpec.createVersionSpec(a.getGroupId(), a.getArtifactId(), 
+                    a.getType(), a.getClassifier(), a.getVersion(), a.isOptional(), a);
+        }
+    }
+    
+    @NbBundle.Messages({
+        "ERR_DependencyOnBrokenProject=Unable to collect dependencies from a broken project",
+        "ERR_DependencyNotPrimed=Unable to collect dependencies from a broken project",
+        "ERR_DependencyMissing=Cannot resolve project dependencies",
+        "ERR_DependencyGraphError=Cannot construct dependency graph"
+    })
+    @Override
+    public DependencyResult findDependencies(Collection<Scope> scopes, Dependency.Filter filter) {
+        init();
+        MavenProject mp = nbMavenProject.getMavenProject();
+        if (NbMavenProject.isErrorPlaceholder(mp)) {
+            if (nbMavenProject.isMavenProjectLoaded()) {
+                throw new ProjectOperationException(project, ProjectOperationException.State.BROKEN, Bundle.ERR_DependencyOnBrokenProject());
+            } else {
+                throw new ProjectOperationException(project, ProjectOperationException.State.UNINITIALIZED, Bundle.ERR_DependencyNotPrimed());
+            }
+        }
+        MavenEmbedder embedder = EmbedderFactory.getProjectEmbedder();
+        MavenExecutionRequest req = embedder.createMavenExecutionRequest();
+        req.setPom(mp.getFile());
+        req.setOffline(true);
+        
+        ProjectBuildingRequest configuration = req.getProjectBuildingRequest();
+        configuration.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
+        configuration.setResolveDependencies(true);
+        
+        Collection<String> mavenScopes = scopes.stream().
+                map(MavenDependenciesImplementation::mavenScope).
+                collect(Collectors.toList());
+        
+        ArtifactFilter artFilter = new CumulativeScopeArtifactFilter(mavenScopes);
+        
+        DependencyGraphBuilder depBuilder = embedder.lookupComponent(DependencyGraphBuilder.class);
+        DependencyNode n;
+        try {
+            DefaultMaven maven = (DefaultMaven)embedder.getPlexus().lookup(Maven.class);
+            configuration.setRepositorySession(maven.newRepositorySession(req));
+            MavenProject copy = mp.clone();
+            copy.setProjectBuildingRequest(configuration);
+            n = depBuilder.buildDependencyGraph(copy, artFilter);
+        } catch (DependencyGraphBuilderException ex) {
+            Throwable cause = ex.getCause();
+            if (cause instanceof DependencyResolutionException) {
+                throw new ProjectOperationException(project, ProjectOperationException.State.BROKEN, 
+                        Bundle.ERR_DependencyMissing(), ex);
+            } else {
+                Exceptions.printStackTrace(ex);
+                return null;
+            }
+        } catch (ComponentLookupException ex) {
+            Exceptions.printStackTrace(ex);
+            // unavailable
+            return null;
+        }
+        
+        return new Result(nbMavenProject.getMavenProject(), 
+                convert(n, filter), new ArrayList<>(scopes));
+    }
+    
+    static Scope scope(Artifact a) {
+        String as = a.getScope();
+        if (as == null) {
+            return Scopes.COMPILE;
+        }
+        switch (as) {
+            case Artifact.SCOPE_COMPILE:
+                return Scopes.COMPILE;
+                
+            case Artifact.SCOPE_RUNTIME:
+            case Artifact.SCOPE_COMPILE_PLUS_RUNTIME:
+            case Artifact.SCOPE_RUNTIME_PLUS_SYSTEM:
+                return Scopes.RUNTIME;
+                
+            case Artifact.SCOPE_IMPORT:
+            case Artifact.SCOPE_SYSTEM:
+                return Scopes.EXTERNAL;
+                
+            case Artifact.SCOPE_TEST:
+                return Scopes.TEST;
+            default:
+                return Scopes.COMPILE;
+        }
+    }
+    
+    private Dependency convert(DependencyNode n, Dependency.Filter filter) {
+        List<Dependency> ch = new ArrayList<>();
+        for (DependencyNode c : n.getChildren()) {
+            Dependency cd = convert(c, filter);
+            if (cd != null) {
+                ch.add(cd);
+            }
+        }
+        Artifact a = n.getArtifact();
+        ArtifactSpec aspec;
+        String cs = a.getClassifier();
+        if ("".equals(cs)) {
+            cs = null;
+        }
+        if (a.isSnapshot()) {
+            aspec = ArtifactSpec.createSnapshotSpec(a.getGroupId(), a.getArtifactId(), a.getType(), 
+                    cs, a.getVersion(), a.isOptional(), a);
+        } else {
+            aspec = ArtifactSpec.createVersionSpec(a.getGroupId(), a.getArtifactId(), a.getType(), 
+                    cs, a.getVersion(), a.isOptional(), a);
+        }
+        Scope s = scope(a);
+        
+        if (!filter.accept(s, aspec)) {
+            return null;
+        }
+        
+        return Dependency.create(aspec, s, ch, n);
+    }
+    
+    class Result implements DependencyResult, PropertyChangeListener {
+        final MavenProject  project;
+        final Dependency    rootNode;
+        final Collection<Scope> scopes;
+        PropertyChangeListener wL;
+        Model effectiveModel;
+        Map<FileObject, StyledDocument> openedPoms = new HashMap<>();
+        private List<ChangeListener> listeners;
+
+        public Result(MavenProject proj, Dependency rootNode, Collection<Scope> scopes) {
+            this.project = proj;
+            this.rootNode = rootNode;
+            this.scopes = scopes;
+        }
+        
+        @Override
+        public Project getProject() {
+            return MavenDependenciesImplementation.this.project;
+        }
+
+        @Override
+        public Dependency getRoot() {
+            return rootNode;
+        }
+
+        @Override
+        public boolean isValid() {
+            return true;
+        }
+
+        @Override
+        public void addChangeListener(ChangeListener l) {
+            boolean attach = false;
+            synchronized (this) {
+                if (listeners == null) {
+                    attach = true;
+                    listeners = new ArrayList<>();
+                }
+                listeners.add(l);
+            }
+            if (!attach) {
+                return;
+            }
+            wL = WeakListeners.propertyChange(this, nbMavenProject);
+            nbMavenProject.addPropertyChangeListener(wL);
+        }
+
+        @Override
+        public void removeChangeListener(ChangeListener l) {
+            boolean detach = false;
+            synchronized (this) {
+                if (listeners == null) {
+                    return;
+                }
+                listeners.remove(l);
+                if (listeners.isEmpty()) {
+                    nbMavenProject.removePropertyChangeListener(wL);
+                }
+            }
+        }
+
+        @Override
+        public void propertyChange(PropertyChangeEvent evt) {
+            if (!NbMavenProject.PROP_PROJECT.equals(evt.getPropertyName())) {
+                return;
+            }
+            
+            List<ChangeListener> ll;
+            synchronized (this) {
+                if (listeners == null || listeners.isEmpty()) {
+                    return;
+                }
+                ll = new ArrayList<>(listeners);
+            }
+            ChangeEvent e = new ChangeEvent(this);
+            for (ChangeListener l : ll ) {
+                l.stateChanged(e);
+            }
+        }
+        
+        public String toString() {
+            return "Depdenencies for " + getRoot().getArtifact() + " "
+                    + scopes.toString();
+        }
+        
+        public Lookup getLookup() {
+            return Lookup.EMPTY;
+        }
+
+        @NbBundle.Messages("ERR_ModelBuildFailed=Model building failed")
+        @Override
+        public SourceLocation getDeclarationRange(Dependency dep) throws IOException {
+            Model m;
+            if (effectiveModel == null) {
+                ModelBuildingResult res;
+                try {
+                    res = EmbedderFactory.getProjectEmbedder().executeModelBuilder(
+                            project.getFile());
+                } catch (ModelBuildingException ex) {
+                    throw new IOException(Bundle.ERR_ModelBuildFailed(), ex);
+                }
+                synchronized (this) {
+                    if (effectiveModel == null) {
+                        effectiveModel = res.getEffectiveModel();
+                    }
+                }
+            }
+            
+            Dependency topLevel = null;
+            Dependency search = dep;
+            org.apache.maven.model.Dependency selected = null;
+            if (dep.getProjectData() instanceof DependencyNode) {
+                DependencyNode pd = (DependencyNode)dep.getProjectData();
+                if (!(pd == rootNode.getProjectData() || pd.getParent() == rootNode.getProjectData())) {
+                    do {
+                        pd = pd.getParent();
+                    } while (pd.getParent() != rootNode.getProjectData());
+                    
+                    List<Dependency> rootDeps = rootNode.getChildren();
+                    for (Dependency cd : rootDeps) {
+                        if (artifactEquals(cd.getArtifact(), pd.getArtifact())) {
+                            search = cd;
+                            topLevel = cd;
+                            break;
+                        }
+                    }
+                }
+            }
+            
+            for (org.apache.maven.model.Dependency d : effectiveModel.getDependencies()) {
+                if (dependencyEquals(dep, d)) {
+                    selected = d;
+                    break;
+                }
+            }
+            if (selected == null) {
+                return null;
+            }                
+            InputLocation l = selected.getLocation("");
+            InputSource s = l.getSource();
+            String path = s.getLocation();
+            FileObject fo = FileUtil.toFileObject(new File(path));
+            if (fo == null) {
+                return null;
+            }
+            StyledDocument d;
+            
+            synchronized (this) {
+                d = openedPoms.get(fo);
+            }
+            if (d == null) {
+                DataObject dobj = DataObject.find(fo);
+                EditorCookie cake = dobj.getLookup().lookup(EditorCookie.class);
+                if (cake == null) {
+                    return null;
+                }
+                d = cake.openDocument();
+                synchronized (this) {
+                    openedPoms.put(fo, d);
+                }
+            }
+            LineDocument ld = LineDocumentUtils.as(d, LineDocument.class);
+            if (ld == null) {
+                return new SourceLocation(fo, -1, -1, topLevel);
+            } else {
+                int so = LineDocumentUtils.getLineStartFromIndex(ld, l.getLineNumber() - 1) 
+                        + l.getColumnNumber() - 1;
+                int[] depStart = new int[] { so };
+                int[] depEnd = new int[] { so };
+                d.render(() -> {
+                    try {
+                        int from = Math.max(0, so - 15);
+                        String text = ld.getText(from, ld.getLength() - from);
+                        int start = text.lastIndexOf("<dependency", so - from);
+                        if (start > -1) {
+                            depStart[0] = start + from;
+                        }
+                        int end = text.indexOf("</dependency", so - from);
+                        if (end != -1) {
+                            // find the closing ">"
+                            end += 10;
+                            int end2 = text.indexOf(">", end);
+                            if (end2 > 0) {
+                                end = end2 + 1;
+                            }
+                            depEnd[0] = end + from;
+                        }
+                    } catch (BadLocationException ex) {
+                    }
+                });
+                
+                return new SourceLocation(fo, depStart[0], depEnd[0], topLevel);
+            }
+        }
+    }
+    
+    static boolean dependencyEquals(Dependency dspec, org.apache.maven.model.Dependency mavenD) {
+        ArtifactSpec spec = dspec.getArtifact();
+        String mavenClass = mavenD.getClassifier();
+        if ("".equals(mavenClass)) {
+            mavenClass = null;
+        }
+        if (!(
+            Objects.equals(spec.getGroupId(), mavenD.getGroupId()) &&
+            Objects.equals(spec.getArtifactId(), mavenD.getArtifactId()) &&    
+            Objects.equals(spec.getClassifier(), mavenClass)) &&
+            Objects.equals(spec.getVersionSpec(), mavenD.getVersion())) {
+            return false;
+        }
+        if (spec.getType() != null && !Objects.equals(spec.getType(), mavenD.getType())) {
+            return false;
+        }
+        if (dspec.getScope() != null) {
+            if (!Objects.equals(mavenScope(dspec.getScope()), mavenD.getScope())) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    static boolean artifactEquals(ArtifactSpec spec, Artifact mavenA) {
+        String mavenClass = mavenA.getClassifier();
+        if ("".equals(mavenClass)) {
+            mavenClass = null;
+        }
+        if (!(
+            Objects.equals(spec.getGroupId(), mavenA.getGroupId()) &&
+            Objects.equals(spec.getArtifactId(), mavenA.getArtifactId()) &&    
+            Objects.equals(spec.getClassifier(), mavenClass)) &&
+            Objects.equals(spec.getVersionSpec(), mavenA.getVersion())) {
+            return false;
+        }
+        if (spec.getType() != null && !Objects.equals(spec.getType(), mavenA.getType())) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/java/maven/test/unit/data/projects/dependencies/golden/testCompileDependencies b/java/maven/test/unit/data/projects/dependencies/golden/testCompileDependencies
new file mode 100644
index 0000000000..1a83d2ac54
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/golden/testCompileDependencies
@@ -0,0 +1,5 @@
+[ ] nbtest.grp:test-app:12.6[jar] / compilation
+ +-- [ ] nbtest.grp:annotation:12.6[jar] / compilation
+ +-- [ ] nbtest.grp:test-lib:12.6[jar] / compilation
+ |    +-- [ ] javax.annotation:javax.annotation-api:1.3.2[jar] / compilation
+ |    +-- [ ] org.slf4j:slf4j-api:1.7.36[jar] / compilation
diff --git a/java/maven/test/unit/data/projects/dependencies/golden/testRuntimeDependencies b/java/maven/test/unit/data/projects/dependencies/golden/testRuntimeDependencies
new file mode 100644
index 0000000000..58345c74c9
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/golden/testRuntimeDependencies
@@ -0,0 +1,7 @@
+[ ] nbtest.grp:test-app:12.6[jar] / compilation
+ +-- [ ] nbtest.grp:annotation:12.6[jar] / compilation
+ +-- [ ] nbtest.grp:test-lib:12.6[jar] / compilation
+ |    +-- [ ] javax.annotation:javax.annotation-api:1.3.2[jar] / compilation
+ |    +-- [ ] org.slf4j:slf4j-api:1.7.36[jar] / compilation
+ +-- [ ] nbtest.grp:test-lib4:12.6[jar] / runtime
+ +-- [ ] org.slf4j:slf4j-jdk14:1.7.36[jar] / runtime
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/_remote.repositories b/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/_remote.repositories
new file mode 100644
index 0000000000..e390a97c76
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/_remote.repositories
@@ -0,0 +1,4 @@
+#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
+#Tue May 24 16:10:10 CEST 2022
+annotation-12.6.jar>=
+annotation-12.6.pom>=
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.jar.lastUpdated b/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.jar.lastUpdated
new file mode 100644
index 0000000000..11b5dbc900
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.jar.lastUpdated
@@ -0,0 +1,4 @@
+#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
+#Tue May 24 16:09:57 CEST 2022
+https\://repo.maven.apache.org/maven2/.lastUpdated=1653401397770
+https\://repo.maven.apache.org/maven2/.error=
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.jardir/META-INF/MANIFEST.MF b/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.jardir/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..9c4f735e45
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.jardir/META-INF/MANIFEST.MF
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+Archiver-Version: Plexus Archiver
+Created-By: Apache Maven 3.6.0
+Built-By: sdedic
+Build-Jdk: 11.0.5
+
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.jardir/META-INF/maven/nbtest.grp/annotation/pom.properties b/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.jardir/META-INF/maven/nbtest.grp/annotation/pom.properties
new file mode 100644
index 0000000000..09a4e8c243
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.jardir/META-INF/maven/nbtest.grp/annotation/pom.properties
@@ -0,0 +1,5 @@
+#Generated by Maven
+#Mon May 23 17:39:16 CEST 2022
+groupId=nbtest.grp
+artifactId=annotation
+version=12.6
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.jardir/META-INF/maven/nbtest.grp/annotation/pom.xml b/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.jardir/META-INF/maven/nbtest.grp/annotation/pom.xml
new file mode 100644
index 0000000000..2c028d7636
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.jardir/META-INF/maven/nbtest.grp/annotation/pom.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>nbtest.grp</groupId>
+  <artifactId>annotation</artifactId>
+  <version>12.6</version>
+
+  <name>Test processor</name>
+  <description>Annotation library stub</description>
+
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.pom b/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.pom
new file mode 100644
index 0000000000..2c028d7636
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.pom
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>nbtest.grp</groupId>
+  <artifactId>annotation</artifactId>
+  <version>12.6</version>
+
+  <name>Test processor</name>
+  <description>Annotation library stub</description>
+
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.pom.lastUpdated b/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.pom.lastUpdated
new file mode 100644
index 0000000000..6352b7d62b
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/12.6/annotation-12.6.pom.lastUpdated
@@ -0,0 +1,4 @@
+#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
+#Tue May 24 16:09:57 CEST 2022
+https\://repo.maven.apache.org/maven2/.lastUpdated=1653401397537
+https\://repo.maven.apache.org/maven2/.error=
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/maven-metadata-local.xml b/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/maven-metadata-local.xml
new file mode 100644
index 0000000000..7ce406639c
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/annotation/maven-metadata-local.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>nbtest.grp</groupId>
+  <artifactId>annotation</artifactId>
+  <versioning>
+    <release>12.6</release>
+    <versions>
+      <version>12.6</version>
+    </versions>
+    <lastUpdated>20220524141010</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/12.6/_remote.repositories b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/12.6/_remote.repositories
new file mode 100644
index 0000000000..5c1575a64e
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/12.6/_remote.repositories
@@ -0,0 +1,4 @@
+#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
+#Tue May 24 16:10:16 CEST 2022
+test-lib-12.6.jar>=
+test-lib-12.6.pom>=
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/12.6/test-lib-12.6.jardir/META-INF/MANIFEST.MF b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/12.6/test-lib-12.6.jardir/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..9c4f735e45
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/12.6/test-lib-12.6.jardir/META-INF/MANIFEST.MF
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+Archiver-Version: Plexus Archiver
+Created-By: Apache Maven 3.6.0
+Built-By: sdedic
+Build-Jdk: 11.0.5
+
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/12.6/test-lib-12.6.jardir/META-INF/maven/nbtest.grp/test-lib/pom.properties b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/12.6/test-lib-12.6.jardir/META-INF/maven/nbtest.grp/test-lib/pom.properties
new file mode 100644
index 0000000000..c42bdc2429
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/12.6/test-lib-12.6.jardir/META-INF/maven/nbtest.grp/test-lib/pom.properties
@@ -0,0 +1,5 @@
+#Generated by Maven
+#Mon May 23 17:39:32 CEST 2022
+groupId=nbtest.grp
+artifactId=test-lib
+version=12.6
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/12.6/test-lib-12.6.jardir/META-INF/maven/nbtest.grp/test-lib/pom.xml b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/12.6/test-lib-12.6.jardir/META-INF/maven/nbtest.grp/test-lib/pom.xml
new file mode 100644
index 0000000000..ccc6e0e497
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/12.6/test-lib-12.6.jardir/META-INF/maven/nbtest.grp/test-lib/pom.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>nbtest.grp</groupId>
+  <artifactId>test-lib</artifactId>
+  <version>12.6</version>
+
+  <name>Test Library</name>
+  <description>Application Library stub</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>annotation</artifactId>
+            <version>12.6</version>
+        </dependency>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>test-lib3</artifactId>
+            <version>12.6</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.annotation</groupId>
+            <artifactId>javax.annotation-api</artifactId>
+            <version>1.3.2</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.7.36</version>
+        </dependency>
+    </dependencies>
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/12.6/test-lib-12.6.pom b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/12.6/test-lib-12.6.pom
new file mode 100644
index 0000000000..ccc6e0e497
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/12.6/test-lib-12.6.pom
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>nbtest.grp</groupId>
+  <artifactId>test-lib</artifactId>
+  <version>12.6</version>
+
+  <name>Test Library</name>
+  <description>Application Library stub</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>annotation</artifactId>
+            <version>12.6</version>
+        </dependency>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>test-lib3</artifactId>
+            <version>12.6</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.annotation</groupId>
+            <artifactId>javax.annotation-api</artifactId>
+            <version>1.3.2</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.7.36</version>
+        </dependency>
+    </dependencies>
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/maven-metadata-local.xml b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/maven-metadata-local.xml
new file mode 100644
index 0000000000..2d04039810
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib/maven-metadata-local.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>nbtest.grp</groupId>
+  <artifactId>test-lib</artifactId>
+  <versioning>
+    <release>12.6</release>
+    <versions>
+      <version>12.6</version>
+    </versions>
+    <lastUpdated>20220524141016</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/12.6/_remote.repositories b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/12.6/_remote.repositories
new file mode 100644
index 0000000000..0df21522b2
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/12.6/_remote.repositories
@@ -0,0 +1,4 @@
+#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
+#Tue May 24 16:09:51 CEST 2022
+test-lib3-12.6.jar>=
+test-lib3-12.6.pom>=
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/12.6/test-lib3-12.6.jardir/META-INF/MANIFEST.MF b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/12.6/test-lib3-12.6.jardir/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..9c4f735e45
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/12.6/test-lib3-12.6.jardir/META-INF/MANIFEST.MF
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+Archiver-Version: Plexus Archiver
+Created-By: Apache Maven 3.6.0
+Built-By: sdedic
+Build-Jdk: 11.0.5
+
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/12.6/test-lib3-12.6.jardir/META-INF/maven/nbtest.grp/test-lib3/pom.properties b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/12.6/test-lib3-12.6.jardir/META-INF/maven/nbtest.grp/test-lib3/pom.properties
new file mode 100644
index 0000000000..92cd362044
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/12.6/test-lib3-12.6.jardir/META-INF/maven/nbtest.grp/test-lib3/pom.properties
@@ -0,0 +1,5 @@
+#Generated by Maven
+#Mon May 23 17:38:40 CEST 2022
+groupId=nbtest.grp
+artifactId=test-lib3
+version=12.6
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/12.6/test-lib3-12.6.jardir/META-INF/maven/nbtest.grp/test-lib3/pom.xml b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/12.6/test-lib3-12.6.jardir/META-INF/maven/nbtest.grp/test-lib3/pom.xml
new file mode 100644
index 0000000000..aeac16ad9d
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/12.6/test-lib3-12.6.jardir/META-INF/maven/nbtest.grp/test-lib3/pom.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>nbtest.grp</groupId>
+  <artifactId>test-lib3</artifactId>
+  <version>12.6</version>
+
+  <name>Processor library</name>
+
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/12.6/test-lib3-12.6.pom b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/12.6/test-lib3-12.6.pom
new file mode 100644
index 0000000000..aeac16ad9d
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/12.6/test-lib3-12.6.pom
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>nbtest.grp</groupId>
+  <artifactId>test-lib3</artifactId>
+  <version>12.6</version>
+
+  <name>Processor library</name>
+
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/maven-metadata-local.xml b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/maven-metadata-local.xml
new file mode 100644
index 0000000000..db0a10792a
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib3/maven-metadata-local.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>nbtest.grp</groupId>
+  <artifactId>test-lib3</artifactId>
+  <versioning>
+    <release>12.6</release>
+    <versions>
+      <version>12.6</version>
+    </versions>
+    <lastUpdated>20220524140951</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/12.6/_remote.repositories b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/12.6/_remote.repositories
new file mode 100644
index 0000000000..7ff5d83e96
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/12.6/_remote.repositories
@@ -0,0 +1,4 @@
+#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
+#Tue May 24 16:09:41 CEST 2022
+test-lib4-12.6.jar>=
+test-lib4-12.6.pom>=
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/12.6/test-lib4-12.6.jardir/META-INF/MANIFEST.MF b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/12.6/test-lib4-12.6.jardir/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..9c4f735e45
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/12.6/test-lib4-12.6.jardir/META-INF/MANIFEST.MF
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+Archiver-Version: Plexus Archiver
+Created-By: Apache Maven 3.6.0
+Built-By: sdedic
+Build-Jdk: 11.0.5
+
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/12.6/test-lib4-12.6.jardir/META-INF/maven/nbtest.grp/test-lib4/pom.properties b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/12.6/test-lib4-12.6.jardir/META-INF/maven/nbtest.grp/test-lib4/pom.properties
new file mode 100644
index 0000000000..93bf8f5ae5
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/12.6/test-lib4-12.6.jardir/META-INF/maven/nbtest.grp/test-lib4/pom.properties
@@ -0,0 +1,5 @@
+#Generated by Maven
+#Tue May 24 16:09:41 CEST 2022
+groupId=nbtest.grp
+artifactId=test-lib4
+version=12.6
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/12.6/test-lib4-12.6.jardir/META-INF/maven/nbtest.grp/test-lib4/pom.xml b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/12.6/test-lib4-12.6.jardir/META-INF/maven/nbtest.grp/test-lib4/pom.xml
new file mode 100644
index 0000000000..019bcd44e8
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/12.6/test-lib4-12.6.jardir/META-INF/maven/nbtest.grp/test-lib4/pom.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>nbtest.grp</groupId>
+  <artifactId>test-lib4</artifactId>
+  <version>12.6</version>
+
+  <name>Processor library for tests</name>
+
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/12.6/test-lib4-12.6.pom b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/12.6/test-lib4-12.6.pom
new file mode 100644
index 0000000000..019bcd44e8
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/12.6/test-lib4-12.6.pom
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>nbtest.grp</groupId>
+  <artifactId>test-lib4</artifactId>
+  <version>12.6</version>
+
+  <name>Processor library for tests</name>
+
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/maven-metadata-local.xml b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/maven-metadata-local.xml
new file mode 100644
index 0000000000..7cc068073a
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-lib4/maven-metadata-local.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>nbtest.grp</groupId>
+  <artifactId>test-lib4</artifactId>
+  <versioning>
+    <release>12.6</release>
+    <versions>
+      <version>12.6</version>
+    </versions>
+    <lastUpdated>20220524140941</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/12.6/_remote.repositories b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/12.6/_remote.repositories
new file mode 100644
index 0000000000..2844607dad
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/12.6/_remote.repositories
@@ -0,0 +1,4 @@
+#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
+#Tue May 24 16:10:23 CEST 2022
+test-processor-12.6.jar>=
+test-processor-12.6.pom>=
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/12.6/test-processor-12.6.jardir/META-INF/MANIFEST.MF b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/12.6/test-processor-12.6.jardir/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..9c4f735e45
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/12.6/test-processor-12.6.jardir/META-INF/MANIFEST.MF
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+Archiver-Version: Plexus Archiver
+Created-By: Apache Maven 3.6.0
+Built-By: sdedic
+Build-Jdk: 11.0.5
+
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/12.6/test-processor-12.6.jardir/META-INF/maven/nbtest.grp/test-processor/pom.properties b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/12.6/test-processor-12.6.jardir/META-INF/maven/nbtest.grp/test-processor/pom.properties
new file mode 100644
index 0000000000..1069c39778
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/12.6/test-processor-12.6.jardir/META-INF/maven/nbtest.grp/test-processor/pom.properties
@@ -0,0 +1,5 @@
+#Generated by Maven
+#Tue May 24 16:10:23 CEST 2022
+groupId=nbtest.grp
+artifactId=test-processor
+version=12.6
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/12.6/test-processor-12.6.jardir/META-INF/maven/nbtest.grp/test-processor/pom.xml b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/12.6/test-processor-12.6.jardir/META-INF/maven/nbtest.grp/test-processor/pom.xml
new file mode 100644
index 0000000000..db75894480
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/12.6/test-processor-12.6.jardir/META-INF/maven/nbtest.grp/test-processor/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>nbtest.grp</groupId>
+  <artifactId>test-processor</artifactId>
+  <version>12.6</version>
+
+  <name>Test processor</name>
+  <description>Annotation processor library stub</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>nbtest.grp</groupId>
+      <artifactId>annotation</artifactId>
+      <version>12.6</version>
+    </dependency>
+    <dependency>
+      <groupId>nbtest.grp</groupId>
+      <artifactId>test-lib4</artifactId>
+      <version>12.6</version>
+    </dependency>
+  </dependencies>
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/12.6/test-processor-12.6.pom b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/12.6/test-processor-12.6.pom
new file mode 100644
index 0000000000..db75894480
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/12.6/test-processor-12.6.pom
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>nbtest.grp</groupId>
+  <artifactId>test-processor</artifactId>
+  <version>12.6</version>
+
+  <name>Test processor</name>
+  <description>Annotation processor library stub</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>nbtest.grp</groupId>
+      <artifactId>annotation</artifactId>
+      <version>12.6</version>
+    </dependency>
+    <dependency>
+      <groupId>nbtest.grp</groupId>
+      <artifactId>test-lib4</artifactId>
+      <version>12.6</version>
+    </dependency>
+  </dependencies>
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/maven-metadata-local.xml b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/maven-metadata-local.xml
new file mode 100644
index 0000000000..6c0a5cf90c
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/repo/grp/test-processor/maven-metadata-local.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<metadata>
+  <groupId>nbtest.grp</groupId>
+  <artifactId>test-processor</artifactId>
+  <versioning>
+    <release>12.6</release>
+    <versions>
+      <version>12.6</version>
+    </versions>
+    <lastUpdated>20220524141023</lastUpdated>
+  </versioning>
+</metadata>
diff --git a/java/maven/test/unit/data/projects/dependencies/src/annotation/pom.xml b/java/maven/test/unit/data/projects/dependencies/src/annotation/pom.xml
new file mode 100644
index 0000000000..2c028d7636
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/src/annotation/pom.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>nbtest.grp</groupId>
+  <artifactId>annotation</artifactId>
+  <version>12.6</version>
+
+  <name>Test processor</name>
+  <description>Annotation library stub</description>
+
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/src/annotation/src/main/java/README b/java/maven/test/unit/data/projects/dependencies/src/annotation/src/main/java/README
new file mode 100644
index 0000000000..e4427aced7
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/src/annotation/src/main/java/README
@@ -0,0 +1 @@
+Placeholder file, to keep Git happy with otherwise empty dir.
diff --git a/java/maven/test/unit/data/projects/dependencies/src/simpleProject/pom-with-processor-broken.xml b/java/maven/test/unit/data/projects/dependencies/src/simpleProject/pom-with-processor-broken.xml
new file mode 100644
index 0000000000..6c8fd68165
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/src/simpleProject/pom-with-processor-broken.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>nbtest.grp</groupId>
+    <artifactId>test-app</artifactId>
+    <version>12.6</version>
+
+    <name>Test App</name>
+    <description>Test App</description>
+  
+    <dependencies>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>annotation</artifactId>
+            <version>12.6</version>
+        </dependency>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>test-lib</artifactId>
+            <version>12.6</version>
+        </dependency>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>test-lib3</artifactId>
+            <scope>test</scope>
+            <version>12.6</version>
+        </dependency>
+    </dependencies>
+  
+    <build>
+        <!-- To use the plugin goals in your POM or parent POM -->
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.8.1</version>
+                <configuration>
+                    <annotationProcessorPaths>
+                        <path>
+                            <groupId>nbtest.grp</groupId>
+                            <artifactId>test-processor</artifactId>
+                            <version>12.6</version>
+                        </path>            
+                        <path>
+                            <groupId>nbtest.grp</groupId>
+                            <artifactId>foobar</artifactId>
+                            <version>12.6</version>
+                        </path>            
+                    </annotationProcessorPaths>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/src/simpleProject/pom-with-processor.xml b/java/maven/test/unit/data/projects/dependencies/src/simpleProject/pom-with-processor.xml
new file mode 100644
index 0000000000..4c07959647
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/src/simpleProject/pom-with-processor.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>nbtest.grp</groupId>
+    <artifactId>test-app</artifactId>
+    <version>12.6</version>
+
+    <name>Test App</name>
+    <description>Test App</description>
+  
+    <dependencies>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>annotation</artifactId>
+            <version>12.6</version>
+        </dependency>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>test-lib</artifactId>
+            <version>12.6</version>
+        </dependency>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>test-lib3</artifactId>
+            <scope>test</scope>
+            <version>12.6</version>
+        </dependency>
+    </dependencies>
+  
+    <build>
+        <!-- To use the plugin goals in your POM or parent POM -->
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.8.1</version>
+                <configuration>
+                    <annotationProcessorPaths>
+                        <path>
+                            <groupId>nbtest.grp</groupId>
+                            <artifactId>test-processor</artifactId>
+                            <version>12.6</version>
+                        </path>            
+                        <path>
+                            <groupId>nbtest.grp</groupId>
+                            <artifactId>test-lib2</artifactId>
+                            <version>12.6</version>
+                        </path>            
+                    </annotationProcessorPaths>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/src/simpleProject/pom-with-separateProcessors.xml b/java/maven/test/unit/data/projects/dependencies/src/simpleProject/pom-with-separateProcessors.xml
new file mode 100644
index 0000000000..14e3f0d026
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/src/simpleProject/pom-with-separateProcessors.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>nbtest.grp</groupId>
+    <artifactId>test-app</artifactId>
+    <version>12.6</version>
+
+    <name>Test App</name>
+    <description>Test App</description>
+  
+    <dependencies>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>annotation</artifactId>
+            <version>12.6</version>
+        </dependency>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>test-lib</artifactId>
+            <version>12.6</version>
+        </dependency>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>test-lib3</artifactId>
+            <scope>test</scope>
+            <version>12.6</version>
+        </dependency>
+    </dependencies>
+  
+    <build>
+        <!-- To use the plugin goals in your POM or parent POM -->
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.8.1</version>
+                <executions>
+                    <execution>
+                        <id>default-compile</id>
+                        <phase>compile</phase>
+                        <!--
+                        <goals>
+                            <goal>testCompile</goal>                            
+                        </goals>
+                        -->
+                        <configuration>
+                            <annotationProcessorPaths>
+                                <path>
+                                    <groupId>nbtest.grp</groupId>
+                                    <artifactId>test-processor</artifactId>
+                                    <version>12.6</version>
+                                </path>            
+                                <path>
+                                    <groupId>nbtest.grp</groupId>
+                                    <artifactId>test-lib2</artifactId>
+                                    <version>12.6</version>
+                                </path>            
+                            </annotationProcessorPaths>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>default-testCompile</id>
+                        <phase>test-compile</phase>
+                        <!--
+                        <goals>
+                            <goal>testCompile</goal>                            
+                        </goals>
+                        -->
+                        <configuration>
+                            <annotationProcessorPaths>
+                                <path>
+                                    <groupId>nbtest.grp</groupId>
+                                    <artifactId>test-processor</artifactId>
+                                    <version>12.6</version>
+                                </path>            
+                                <path>
+                                    <groupId>nbtest.grp</groupId>
+                                    <artifactId>test-lib4</artifactId>
+                                    <version>12.6</version>
+                                </path>            
+                            </annotationProcessorPaths>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/src/simpleProject/pom.xml b/java/maven/test/unit/data/projects/dependencies/src/simpleProject/pom.xml
new file mode 100644
index 0000000000..85e4336399
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/src/simpleProject/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>nbtest.grp</groupId>
+    <artifactId>test-app</artifactId>
+    <version>12.6</version>
+
+    <name>Test App</name>
+    <description>Test App</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>annotation</artifactId>
+            <version>12.6</version>
+        </dependency>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>test-lib</artifactId>
+            <version>12.6</version>
+        </dependency>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>test-lib4</artifactId>
+            <version>12.6</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>test-lib3</artifactId>
+            <scope>test</scope>
+            <version>12.6</version>
+        </dependency>
+    
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-jdk14</artifactId>
+            <version>1.7.36</version>
+            <scope>runtime</scope>
+        </dependency>
+
+    </dependencies>
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/src/simpleProject/src/main/java/README b/java/maven/test/unit/data/projects/dependencies/src/simpleProject/src/main/java/README
new file mode 100644
index 0000000000..e4427aced7
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/src/simpleProject/src/main/java/README
@@ -0,0 +1 @@
+Placeholder file, to keep Git happy with otherwise empty dir.
diff --git a/java/maven/test/unit/data/projects/dependencies/src/simpleProject/src/test/java/README b/java/maven/test/unit/data/projects/dependencies/src/simpleProject/src/test/java/README
new file mode 100644
index 0000000000..e4427aced7
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/src/simpleProject/src/test/java/README
@@ -0,0 +1 @@
+Placeholder file, to keep Git happy with otherwise empty dir.
diff --git a/java/maven/test/unit/data/projects/dependencies/src/test-lib/pom.xml b/java/maven/test/unit/data/projects/dependencies/src/test-lib/pom.xml
new file mode 100644
index 0000000000..ccc6e0e497
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/src/test-lib/pom.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>nbtest.grp</groupId>
+  <artifactId>test-lib</artifactId>
+  <version>12.6</version>
+
+  <name>Test Library</name>
+  <description>Application Library stub</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>annotation</artifactId>
+            <version>12.6</version>
+        </dependency>
+        <dependency>
+            <groupId>nbtest.grp</groupId>
+            <artifactId>test-lib3</artifactId>
+            <version>12.6</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.annotation</groupId>
+            <artifactId>javax.annotation-api</artifactId>
+            <version>1.3.2</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.7.36</version>
+        </dependency>
+    </dependencies>
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/src/test-lib/src/main/java/README b/java/maven/test/unit/data/projects/dependencies/src/test-lib/src/main/java/README
new file mode 100644
index 0000000000..e4427aced7
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/src/test-lib/src/main/java/README
@@ -0,0 +1 @@
+Placeholder file, to keep Git happy with otherwise empty dir.
diff --git a/java/maven/test/unit/data/projects/dependencies/src/test-lib3/pom.xml b/java/maven/test/unit/data/projects/dependencies/src/test-lib3/pom.xml
new file mode 100644
index 0000000000..aeac16ad9d
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/src/test-lib3/pom.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>nbtest.grp</groupId>
+  <artifactId>test-lib3</artifactId>
+  <version>12.6</version>
+
+  <name>Processor library</name>
+
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/src/test-lib3/src/main/java/README b/java/maven/test/unit/data/projects/dependencies/src/test-lib3/src/main/java/README
new file mode 100644
index 0000000000..e4427aced7
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/src/test-lib3/src/main/java/README
@@ -0,0 +1 @@
+Placeholder file, to keep Git happy with otherwise empty dir.
diff --git a/java/maven/test/unit/data/projects/dependencies/src/test-lib4/pom.xml b/java/maven/test/unit/data/projects/dependencies/src/test-lib4/pom.xml
new file mode 100644
index 0000000000..019bcd44e8
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/src/test-lib4/pom.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>nbtest.grp</groupId>
+  <artifactId>test-lib4</artifactId>
+  <version>12.6</version>
+
+  <name>Processor library for tests</name>
+
+</project>
+
diff --git a/java/maven/test/unit/data/projects/dependencies/src/test-lib4/src/main/java/README b/java/maven/test/unit/data/projects/dependencies/src/test-lib4/src/main/java/README
new file mode 100644
index 0000000000..e4427aced7
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/src/test-lib4/src/main/java/README
@@ -0,0 +1 @@
+Placeholder file, to keep Git happy with otherwise empty dir.
diff --git a/java/maven/test/unit/data/projects/dependencies/src/test-processor/pom.xml b/java/maven/test/unit/data/projects/dependencies/src/test-processor/pom.xml
new file mode 100644
index 0000000000..db75894480
--- /dev/null
+++ b/java/maven/test/unit/data/projects/dependencies/src/test-processor/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>nbtest.grp</groupId>
+  <artifactId>test-processor</artifactId>
+  <version>12.6</version>
+
+  <name>Test processor</name>
+  <description>Annotation processor library stub</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>nbtest.grp</groupId>
+      <artifactId>annotation</artifactId>
+      <version>12.6</version>
+    </dependency>
+    <dependency>
+      <groupId>nbtest.grp</groupId>
+      <artifactId>test-lib4</artifactId>
+      <version>12.6</version>
+    </dependency>
+  </dependencies>
+</project>
+
diff --git a/java/maven/test/unit/src/org/netbeans/modules/maven/queries/MavenDependenciesImplementationTest.java b/java/maven/test/unit/src/org/netbeans/modules/maven/queries/MavenDependenciesImplementationTest.java
new file mode 100644
index 0000000000..a89f9de8f5
--- /dev/null
+++ b/java/maven/test/unit/src/org/netbeans/modules/maven/queries/MavenDependenciesImplementationTest.java
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.maven.queries;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import static junit.framework.TestCase.assertNotNull;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectManager;
+import org.netbeans.junit.NbTestCase;
+import org.netbeans.modules.maven.api.NbMavenProject;
+import org.netbeans.modules.maven.embedder.EmbedderFactory;
+import org.netbeans.modules.project.dependency.Dependency;
+import org.netbeans.modules.project.dependency.DependencyResult;
+import org.netbeans.modules.project.dependency.ProjectDependencies;
+import org.netbeans.modules.project.dependency.Scopes;
+import org.netbeans.modules.project.dependency.SourceLocation;
+import org.netbeans.spi.project.ActionProgress;
+import org.netbeans.spi.project.ActionProvider;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.modules.DummyInstalledFileLocator;
+import org.openide.util.lookup.Lookups;
+import org.openide.windows.IOProvider;
+
+/**
+ *
+ * @author sdedic
+ */
+public class MavenDependenciesImplementationTest extends NbTestCase {
+    private FileObject d;
+    private File repo;
+    private FileObject repoFO;
+    private FileObject dataFO;
+
+    public MavenDependenciesImplementationTest(String name) {
+        super(name);
+    }
+    
+    // InstalledFilesLocator is needed so that Maven module finds maven's installation
+    @org.openide.util.lookup.ServiceProvider(service=org.openide.modules.InstalledFileLocator.class, position = 1000)
+    public static class InstalledFileLocator extends DummyInstalledFileLocator {
+    }
+
+    private static File getTestNBDestDir() {
+        String destDir = System.getProperty("test.netbeans.dest.dir");
+        // set in project.properties as test-unit-sys-prop.test.netbeans.dest.dir
+        assertNotNull("test.netbeans.dest.dir property has to be set when running within binary distribution", destDir);
+        return new File(destDir);
+    }
+    protected @Override void setUp() throws Exception {
+        clearWorkDir();
+        
+        // This is needed, otherwose the core window's startup code will redirect
+        // System.out/err to the IOProvider, and its Trivial implementation will redirect
+        // it back to System.err - loop is formed. Initialize IOProvider first, it gets
+        // the real System.err/out references.
+        IOProvider p = IOProvider.getDefault();
+        d = FileUtil.toFileObject(getWorkDir());
+        System.setProperty("test.reload.sync", "true");
+        repo = EmbedderFactory.getProjectEmbedder().getLocalRepositoryFile();
+        repoFO = FileUtil.toFileObject(repo);
+        dataFO = FileUtil.toFileObject(getDataDir());
+        
+        // Configure the DummyFilesLocator with NB harness dir
+        File destDirF = getTestNBDestDir();
+        DummyInstalledFileLocator.registerDestDir(destDirF);
+    }
+    
+    private void installCompileResources() throws Exception {
+        FileUtil.copyFile(dataFO.getFileObject("projects/dependencies/repo"), repoFO, "nbtest");
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        FileObject nbtest = repoFO.getFileObject("nbtest");
+        if (nbtest != null && nbtest.isValid()) {
+            nbtest.delete();
+        }
+    }
+    
+    /**
+     * Primes the project including dependency fetch, waits for the operation to complete.
+     * @throws Exception 
+     */
+    void primeProject(Project p) throws Exception {
+        ActionProvider ap = p.getLookup().lookup(ActionProvider.class);
+        if (ap == null) {
+            throw new IllegalStateException("No action provider");
+        }
+        assertTrue(Arrays.asList(ap.getSupportedActions()).contains(ActionProvider.COMMAND_PRIME));
+        
+        CountDownLatch primeLatch = new CountDownLatch(1);
+        ActionProgress prg = new ActionProgress() {
+            @Override
+            protected void started() {
+            }
+
+            @Override
+            public void finished(boolean success) {
+                primeLatch.countDown();
+            }
+        };
+        ap.invokeAction(ActionProvider.COMMAND_PRIME, Lookups.fixed(prg));
+        primeLatch.await(20, TimeUnit.SECONDS);
+    }
+    
+    public void testCompileDependencies() throws Exception {
+        FileUtil.toFileObject(getWorkDir()).refresh();
+        installCompileResources();
+        
+        FileObject testApp = dataFO.getFileObject("projects/dependencies/src/simpleProject");
+        FileObject prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "simpleProject");
+        
+        Project p = ProjectManager.getDefault().findProject(prjCopy);
+        assertNotNull(p);
+        
+        primeProject(p);
+        
+        DependencyResult dr = ProjectDependencies.findDependencies(p, null, Scopes.COMPILE);
+        Dependency root = dr.getRoot();
+        assertContents(printDependencyTree(root), getName());
+    }
+    
+    public void testRuntimeDependencies() throws Exception {
+        FileUtil.toFileObject(getWorkDir()).refresh();
+        installCompileResources();
+        
+        FileObject testApp = dataFO.getFileObject("projects/dependencies/src/simpleProject");
+        FileObject prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "simpleProject");
+        
+        Project p = ProjectManager.getDefault().findProject(prjCopy);
+        assertNotNull(p);
+        
+        primeProject(p);
+        
+        DependencyResult dr = ProjectDependencies.findDependencies(p, null, Scopes.RUNTIME);
+        Dependency root = dr.getRoot();
+        assertContents(printDependencyTree(root), getName());
+    }
+    
+    public void testDirectDependencySource() throws Exception {
+        FileUtil.toFileObject(getWorkDir()).refresh();
+        installCompileResources();
+        
+        FileObject testApp = dataFO.getFileObject("projects/dependencies/src/simpleProject");
+        FileObject prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "simpleProject");
+        
+        Project p = ProjectManager.getDefault().findProject(prjCopy);
+        assertNotNull(p);
+ 
+        primeProject(p);
+
+        DependencyResult dr = ProjectDependencies.findDependencies(p, null, Scopes.RUNTIME);
+        
+        Dependency dep = dr.getRoot().getChildren().stream().filter(d -> d.getArtifact().getArtifactId().equals("test-lib")).findAny().get();
+        SourceLocation srcLoc = dr.getDeclarationRange(dep);
+        assertNotNull(srcLoc);
+        assertFalse(srcLoc.isEmpty());
+        assertTrue(srcLoc.hasPosition());
+        
+        Path pomPath = p.getLookup().lookup(NbMavenProject.class).getMavenProject().getFile().toPath();
+        assertEquals(pomPath.toFile(), FileUtil.toFile(srcLoc.getFile()));
+
+        String s = String.join("\n", Files.readAllLines(pomPath));
+        assertEquals("<dependency", s.substring(srcLoc.getStartOffset(), srcLoc.getStartOffset() + 11));
+        assertEquals("</dependency>", s.substring(srcLoc.getEndOffset() - 13, srcLoc.getEndOffset()));
+    }
+    
+    public void testNestedDependencySource() throws Exception {
+        FileUtil.toFileObject(getWorkDir()).refresh();
+        installCompileResources();
+        
+        FileObject testApp = dataFO.getFileObject("projects/dependencies/src/simpleProject");
+        FileObject prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "simpleProject");
+        
+        Project p = ProjectManager.getDefault().findProject(prjCopy);
+        assertNotNull(p);
+
+        primeProject(p);
+
+        DependencyResult dr = ProjectDependencies.findDependencies(p, null, Scopes.RUNTIME);
+        
+        Dependency libDep = dr.getRoot().getChildren().stream().filter(d -> d.getArtifact().getArtifactId().equals("test-lib")).findAny().get();
+        Dependency annoDep = libDep.getChildren().stream().filter(d -> d.getArtifact().getArtifactId().equals("javax.annotation-api")).findAny().get();
+
+        SourceLocation srcLoc = dr.getDeclarationRange(annoDep);
+
+        Path pomPath = p.getLookup().lookup(NbMavenProject.class).getMavenProject().getFile().toPath();
+        assertEquals(pomPath.toFile(), FileUtil.toFile(srcLoc.getFile()));
+
+        String s = String.join("\n", Files.readAllLines(pomPath));
+        assertEquals("<dependency", s.substring(srcLoc.getStartOffset(), srcLoc.getStartOffset() + 11));
+        assertEquals("</dependency>", s.substring(srcLoc.getEndOffset() - 13, srcLoc.getEndOffset()));
+    }
+    
+    void assertContents(String contents, String golden) throws IOException {
+        File f = new File(getDataDir(), "projects/dependencies/golden/" + golden);
+        Path res = Files.write(getWorkDir().toPath().resolve(getName() + ".output"), 
+                Arrays.asList(contents.split("\n")),
+                StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
+        assertFile(res.toFile(), f, new File(getWorkDir(), getName() + ".diff"));
+    }
+    
+    static String printDependencyTree(Dependency root) {
+        StringBuilder sb = new StringBuilder();
+        printDependencyTree(root, -1, sb);
+        return sb.toString();
+    }
+
+    static void printDependencyTree(Dependency from, int levels, StringBuilder sb) {
+        if (levels >= 0) {
+            sb.append(" ");
+        }
+        for (int i = 0; i < levels; i++) {
+            sb.append("|    ");
+        }
+        if (levels < 0) {
+            sb.append("[ ] ");
+        } else {
+            sb.append("+-- [ ] ");
+        }
+        sb.append(from.getArtifact());
+        if (from.getScope() != null) {
+            sb.append(" / "); sb.append(from.getScope());
+        }
+        sb.append("\n");
+        int index = 0;
+        for (Dependency c : (List<Dependency>)from.getChildren()) {
+            printDependencyTree(c, levels + 1, sb);
+            index++;
+        }
+    }
+}
diff --git a/nbbuild/cluster.properties b/nbbuild/cluster.properties
index a145e8af37..2759c5d99f 100644
--- a/nbbuild/cluster.properties
+++ b/nbbuild/cluster.properties
@@ -498,6 +498,7 @@ nb.cluster.ide=\
         project.ant,\
         project.ant.compat8,\
         project.ant.ui,\
+        project.dependency,\
         project.indexingbridge,\
         project.libraries,\
         project.libraries.ui,\


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists