Skip to content

Commit 6326abe

Browse files
authored
Merge pull request #5 from oracle-devrel/jar-scanner-project
Jar scanner project
2 parents 3a83519 + 6ce27d1 commit 6326abe

37 files changed

+6880
-4
lines changed

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,8 @@ Temporary Items
3030
.key
3131
.crt
3232
.csr
33-
.pem
33+
.pem
34+
functions-hmac/.settings/org.eclipse.jdt.core.prefs
35+
functions-hmac/.settings/org.eclipse.jdt.apt.core.prefs
36+
functions-hmac/.factorypath
37+
functions-hmac/.classpath

dependencyanalyser/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/target/
2+
/.classpath
3+
/.factorypath
4+
/.project
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/org.eclipse.jdt.apt.core.prefs
2+
/org.eclipse.jdt.core.prefs
3+
/org.eclipse.m2e.core.prefs

dependencyanalyser/README.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# Dependency Scanner
2+
3+
This program will scan the dependency sources it is given and build a combined dependency tree combining the separate dependency trees for the inputs. This allows the detection of conflicting dependencies. While maven (and other build tools) can of course determine conflicting dependencies in the jar files they manage (and copy into the resulting targets) this only applies at compile time, not run time, where a jar file is provided by the end user (or the end user replaces a jar file in the inputs). The goal of this program is to enable the provision of a set of the top level input jar files and the dependency trees for each will be checked for conflicting versions. For example a developer may build an application against what will ultimately be a user supplied library (the maven `provided` scope). At the compile stage the application will be compiled against the version in that build, however a user may subsequently use a different version of that library (and the jar files associated with it) If the original compiled version had a different version of the library which was replaced (or the provided version was replaced by the developer mandated version) then conflicts may occur.
4+
5+
## Usage
6+
The class `com.oracle.timg.demo.dependencyanalyser.DependencyScanner` is the main class. is supports the following arguments:
7+
8+
`-d`/`--directory` followed by working directory location - required when doing something that generates an intermediate file, for example extracting a pom.xml or generating a graph-xml file. In practice (with the current loaders) this basically means in all situation. Defaults to the current directory and can be absolute or relative, it must exist and of course you must be able to read and write it.
9+
10+
`-g`/`--groupid` followed by groupid - Optional and used for setting the groupid at the root of the combined dependency tree, defaults to `my.company` if not set. Recommended if listing jar files or similar so you can determine what the actual tree root will be in the output
11+
12+
`-a`/`--artifactid` followed by artifactid - Optional and used for setting the artifact at the root of the combined dependency tree, defaults to `myartifact` if not set. Recommended if listing jar files or similar so you can determine what the actual tree root will be in the output
13+
14+
`-v`/`--version` followed by version string - Optional and used for setting the version at the root of the combined dependency tree, defaults to `0.0.0` if not set. Recommended if listing jar files or similar so you can determine what the actual tree root will be in the output
15+
16+
`-m`/`--maven-path` followed by path - Required for all sources that are maven based (so pom.xmnl files of jar files with a ponm.xml contents. Specified the location of the mvn executabler. Note that this **MUST** be the full absolute path, there is no default as this is system dependent.
17+
18+
`-r`/`--resolve-dependencies` - If set will call any pre-resolving task needed before generating dependency data, used for example to ensure that the local mavan repo has ll of the dependencies downloaded. Defaults to false.
19+
20+
`-i`/`--retain-intermediates` - If set will retain the intermediate files (e.g. extracted pom.xml) used for the processing stages, this can be useful for debugging purposes. Defaults to false.
21+
22+
`-V`/`--Verbose` - outputs info re the sub processes that are run (e.g. command lines being used, output from the sub processes)
23+
24+
25+
The remaining arguments are treated as input sources. Currently the following are supported.
26+
27+
Files with the suffix `.mvn-graphml.xml` These are assumed to contain a GraphML "dump" of the dependencies in the format that Maven outputs. The file will be directly loaded and to locate the root of the dependency tree all loaded jars are scanned to find a jar version which does not depend on any other source. This resulting tree will be added to the combined dependencies tree. The root of this source will be created as a sub node under the combined root tree and will have it's scope set to 'ROOT',
28+
29+
Files with the name `pom.xml` - These files will be passed to maven to create a maven dependency graqph file (with the suffix `.mvn-graphml.xml`) which will then be loaded and added to the combined dependencies tree using the process above if the `-r` flag is set then maven will be asked to do a dependency resolve stage before processing. The .mvn-graplml.xml file will be generated using a temporary name based on thye grupid, artifactid and version located in the ponm.xml file and will be written to the location specified by the `-d` flag, if the `-i` flag is set this temporary file will be retained, otherwise it will be deleted when the jvm exits. If the `-V` flag is set the the command(s) used to run maven and any maven output will be displayed.
30+
31+
Files with the suffix `.jar` are examined to see if they contain a `pom.xml` file and optionally a `pom.properties` file. These are expected to be under the `META-INF/maven/<groupid>/<artifactid>` "directory" in the jar file (If Maven is packaging the jar file it will copy the files there automatically, Gradle seem to also generate at least a `pom.xml` file which is places there as well). If present the `pom.properties` file will be used to get the groupid, artifactid and version, if `pom.properties` is not present these will be extracted from the `pom.xml` entri. The `META-INF/maven/<groupid>/<artifactid>/pom.xml` entry in the jar file will then be extracted and copied into a temporaty file and then the process above is done as with a "normal" pom.xml file.
32+
33+
## Outputs
34+
35+
The DependencyScanner class is provided as an example, it loads each of the source arguments in turn and then generates the output. There are a number of utility medhods in the JarTree class that can be used to locate jar file versions based on different criteria and also to dump the dependeny tree.
36+
37+
Count of the number of Jar files where there are two or move versions in the combined dependency tree
38+
39+
Information on each oif the jar files with multiple versions including the jar file versions that depend in this version, any jar file versions that they depend on and also details of the original source jar file version to help identify wherte conflicting versions originate from (this maps to the input sources).
40+
41+
It will also list the number of jar file versions that have no dependencies (i.e. "leaf" jar file versions) and also the bymber of jar file versions. Depending on the other flags and arguments other output may of course be provided.
42+
43+
Below is the core output from test code. This is deliberately using different versions of Lombok, please note that the number of jar file versions with nothign depending should always be one (this being the "root / project" dependency.
44+
45+
```text
46+
May 20, 2024 2:42:23 PM com.oracle.timg.demo.dependencyanalyser.DependencyScanner main
47+
INFO: Count of combined Jar files with two or more versions
48+
3
49+
May 20, 2024 2:42:23 PM com.oracle.timg.demo.dependencyanalyser.DependencyScanner main
50+
INFO: Details of jar files with multiple versions
51+
org.projectlombok:lombok
52+
1.18.30 refs = 1
53+
Depends on
54+
Depended on by
55+
com.oracle.labs.helidon.fileio:filewriter:1.0.0 (PROVIDED)
56+
In source
57+
com.oracle.labs.helidon.fileio:filewriter:1.0.0 from origional source testdata/filewriter.mvn-graphml.xml
58+
59+
1.18.32 refs = 2
60+
Depends on
61+
Depended on by
62+
com.oracle.timg.demo:dependencyanalyser:0.0.1-SNAPSHOT (PROVIDED)
63+
com.oracle.labs.helidon.fileio:filereader:1.0.0 (PROVIDED)
64+
In source
65+
com.oracle.timg.demo:dependencyanalyser:0.0.1-SNAPSHOT from origional source testdata/pom.xml
66+
com.oracle.labs.helidon.fileio:filereader:1.0.0 from origional source testdata/filereader.mvn-graphml.xml
67+
68+
org.apiguardian:apiguardian-api
69+
1.0.0 refs = 1
70+
Depends on
71+
Depended on by
72+
com.oracle.labs.helidon.fileio:filereader:1.0.0 (COMPILE)
73+
In source
74+
com.oracle.labs.helidon.fileio:filereader:1.0.0 from origional source testdata/filereader.mvn-graphml.xml
75+
76+
1.1.2 refs = 1
77+
Depends on
78+
Depended on by
79+
org.junit.jupiter:junit-jupiter-api:5.9.3 (TEST)
80+
In source
81+
com.oracle.labs.helidon.fileio:filewriter:1.0.0 from origional source testdata/filewriter.mvn-graphml.xml
82+
83+
jakarta.activation:jakarta.activation-api
84+
1.2.2 refs = 1
85+
Depends on
86+
Depended on by
87+
jakarta.xml.bind:jakarta.xml.bind-api:2.3.3 (COMPILE)
88+
In source
89+
com.oracle.timg.demo:dependencyanalyser:0.0.1-SNAPSHOT from origional source testdata/pom.xml
90+
91+
2.1.1 refs = 2
92+
Depends on
93+
Depended on by
94+
com.oracle.labs.helidon.fileio:filewriter:1.0.0 (COMPILE)
95+
com.oracle.labs.helidon.fileio:filereader:1.0.0 (COMPILE)
96+
In source
97+
com.oracle.labs.helidon.fileio:filewriter:1.0.0 from origional source testdata/filewriter.mvn-graphml.xml
98+
99+
100+
May 20, 2024 2:42:23 PM com.oracle.timg.demo.dependencyanalyser.DependencyScanner main
101+
INFO: Combined Jar versions with no dependencies 87
102+
May 20, 2024 2:42:23 PM com.oracle.timg.demo.dependencyanalyser.DependencyScanner main
103+
INFO: Combined Jar versions with no depended on 1
104+
```
105+
106+
107+
108+
## Known limitations
109+
110+
This program uses Mavan to build the per project tree, the program then loads the maven dependency output and combines it with all other supplied outputs. Of course this means that the mvn command needs to be available. it also means that it is subject to mavens restrictions and limitations. Known factors that may cause a problem are :
111+
112+
1. You need to have resolved all the dependencies in any pom.xml (or jar file containing it) to do that the program has the option of running a maven resolve stage (set the `-r` flag), this can take a while and you will need a network connection and enough space on the machine you are using to download the dependencies.
113+
114+
2. Maven supports the operation of relative parent pom.xml, for some projects where the jar file (or pom.xml) is not in the local maven repository this may be a problem as the parent pom may not be in the right place in the directory tree, in some situations where there happens to be a pom.xml (not not the expected one) in the location specified by the relativePath this will result in maven loading the incorrect parent pom.
115+
116+
3. Of course if mvn output changes (or the mvn command and flags change) then this will be a problem.
117+
118+
## Extending the code
119+
120+
Is is architecturally possible to add additional sources of dependency information. The new loader needs to implement the SourceLoader interface, the GetSourceLoader class needs to be updated to recognize (by whatever means you like) the new source type and return an instance of the appropriate loader.
121+
122+
The loadDependencied method needs to return a new Jar Tree which will then be combined with all of the others that have been built. The new Jar Tree has the following criteria.
123+
124+
The getRoot method must return an IdenfitiedJarFileVersion which is the root of the new dependency structure, this must not have anything depending on it.
125+
126+
This must be a tree, no loops are allowed (this is really a limitation of the output mechanisms)
127+
128+
Every IdenfitiedJarFileVersion in the tree must contain the tree being built in the sourceProjecxtrs set (this will be combined with the other sources later and used in the output to trace the source of multiple dependencies

dependencyanalyser/pom.xml

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
2+
<!-- Copyright (c) 2023 Oracle and/or its affiliates.
3+
4+
The Universal Permissive License (UPL), Version 1.0
5+
6+
Subject to the condition set forth below, permission is hereby granted to any
7+
person obtaining a copy of this software, associated documentation and/or data
8+
(collectively the "Software"), free of charge and under any and all copyright
9+
rights in the Software, and any and all patent rights owned or freely
10+
licensable by each licensor hereunder covering either (i) the unmodified
11+
Software as contributed to or provided by such licensor, or (ii) the Larger
12+
Works (as defined below), to deal in both
13+
14+
(a) the Software, and
15+
(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
one is included with the Software (each a "Larger Work" to which the Software
17+
is contributed by such licensors),
18+
19+
without restriction, including without limitation the rights to copy, create
20+
derivative works of, display, perform, and distribute the Software and make,
21+
use, sell, offer for sale, import, export, have made, and have sold the
22+
Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
either these or other terms.
24+
25+
This license is subject to the following condition:
26+
The above copyright notice and either this complete permission notice or at
27+
a minimum a reference to the UPL must be included in all copies or
28+
substantial portions of the Software.
29+
30+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36+
SOFTWARE. -->
37+
<project xmlns="http://maven.apache.org/POM/4.0.0"
38+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
39+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
40+
<modelVersion>4.0.0</modelVersion>
41+
<groupId>com.oracle.timg.demo</groupId>
42+
<artifactId>dependencyanalyser</artifactId>
43+
<version>0.0.1-SNAPSHOT</version>
44+
<name>dependencyanalyser</name>
45+
<description>analysies mvn output file looking for conflicting dependencies</description>
46+
<properties>
47+
<version.lombok>1.18.32</version.lombok>
48+
<version.args4j>2.37</version.args4j>
49+
</properties>
50+
<dependencies>
51+
<!-- Utilities -->
52+
<!-- load int he xml-->
53+
<!-- <dependency>-->
54+
<!-- <groupId>org.openjax.xml</groupId>-->
55+
<!-- <artifactId>sax</artifactId>-->
56+
<!-- <version>1.0.0</version>-->
57+
<!-- </dependency>-->
58+
<!-- XML -->
59+
<dependency>
60+
<groupId>jakarta.xml.bind</groupId>
61+
<artifactId>jakarta.xml.bind-api</artifactId>
62+
<version>2.3.3</version>
63+
</dependency>
64+
<dependency>
65+
<groupId>org.glassfish.jaxb</groupId>
66+
<artifactId>jaxb-runtime</artifactId>
67+
<scope>runtime</scope>
68+
<version>2.3.3</version>
69+
</dependency>
70+
<!-- Lombok does the auto method creation -->
71+
<dependency>
72+
<groupId>org.projectlombok</groupId>
73+
<artifactId>lombok</artifactId>
74+
<version>${version.lombok}</version>
75+
<scope>provided</scope>
76+
</dependency>
77+
<dependency>
78+
<groupId>com.kazurayam</groupId>
79+
<artifactId>subprocessj</artifactId>
80+
<version>0.3.7</version>
81+
</dependency>
82+
<dependency>
83+
<groupId>args4j</groupId>
84+
<artifactId>args4j</artifactId>
85+
<version>${version.args4j}</version>
86+
</dependency>
87+
</dependencies>
88+
</project>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*Copyright (c) 2024 Oracle and/or its affiliates.
2+
3+
The Universal Permissive License (UPL), Version 1.0
4+
5+
Subject to the condition set forth below, permission is hereby granted to any
6+
person obtaining a copy of this software, associated documentation and/or data
7+
(collectively the "Software"), free of charge and under any and all copyright
8+
rights in the Software, and any and all patent rights owned or freely
9+
licensable by each licensor hereunder covering either (i) the unmodified
10+
Software as contributed to or provided by such licensor, or (ii) the Larger
11+
Works (as defined below), to deal in both
12+
13+
(a) the Software, and
14+
(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
15+
one is included with the Software (each a "Larger Work" to which the Software
16+
is contributed by such licensors),
17+
18+
without restriction, including without limitation the rights to copy, create
19+
derivative works of, display, perform, and distribute the Software and make,
20+
use, sell, offer for sale, import, export, have made, and have sold the
21+
Software and the Larger Work(s), and to sublicense the foregoing rights on
22+
either these or other terms.
23+
24+
This license is subject to the following condition:
25+
The above copyright notice and either this complete permission notice or at
26+
a minimum a reference to the UPL must be included in all copies or
27+
substantial portions of the Software.
28+
29+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35+
SOFTWARE.
36+
*/
37+
package com.oracle.timg.demo.dependencyanalyser;
38+
39+
import lombok.Data;
40+
import lombok.EqualsAndHashCode;
41+
42+
@Data
43+
@EqualsAndHashCode
44+
45+
public class Dependency implements Comparable<Dependency> {
46+
@EqualsAndHashCode.Exclude
47+
private final IdentifiedJarVersion source;
48+
@EqualsAndHashCode.Include
49+
private final IdentifiedJarVersion target;
50+
@EqualsAndHashCode.Include
51+
private final ScopeType scope;
52+
53+
@Override
54+
public int compareTo(Dependency dependency) {
55+
return (target.toString() + scope).compareTo(dependency.target.toString() + dependency.scope);
56+
}
57+
58+
public Dependency dupeCore(IdentifiedJarVersion newSource, IdentifiedJarVersion newTarget) {
59+
return new Dependency(newSource, newTarget, this.scope);
60+
}
61+
}

0 commit comments

Comments
 (0)