Skip to content

Commit 64ec0f2

Browse files
committed
Update README and tests to reflect library count feature
- Enhanced README.md to include a new section for counting specific libraries (struts, commons, log4j, cryptix) in dependencies. - Updated tests in package-dependencies.test.ts to validate the counting functionality for specific libraries. - Added methods to track and report library counts in the package dependency extractor.
1 parent f27b771 commit 64ec0f2

File tree

2 files changed

+143
-3
lines changed

2 files changed

+143
-3
lines changed

README.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ The input JSONL files are typically generated from Jarviz-lib static analysis of
1616
- Generate statistics about dependencies
1717
- View the most depended-upon classes
1818
- Extract and analyze package dependencies
19+
- Count instances of specific libraries (struts, commons, log4j, cryptix) in dependencies
1920

2021
## Installation
2122

@@ -164,13 +165,20 @@ No cycles found.
164165

165166
The package dependencies extractor generates a Markdown file with the following sections:
166167

167-
1. **Base Packages**: A list of all base packages used by the project, grouped by:
168+
1. **Specific Library Counts**: Tracks the number of dependencies where the targetClass contains specific libraries:
169+
- Struts
170+
- Commons
171+
- Log4j
172+
- Cryptix
173+
This helps identify and quantify vulnerability exposure if any of these libraries have security issues.
174+
175+
2. **Base Packages**: A list of all base packages used by the project, grouped by:
168176
- External Dependencies (e.g., `java.lang`, `javax.servlet`)
169177
- Internal Packages (e.g., `com.example`)
170178

171-
2. **Dependency Relationships**: Shows which base packages depend on other base packages
179+
3. **Dependency Relationships**: Shows which base packages depend on other base packages
172180

173-
3. **Package Details**: Detailed information about each base package, including:
181+
4. **Package Details**: Detailed information about each base package, including:
174182
- Type (Internal or External)
175183
- Number of sub-packages
176184
- Number of classes

tests/package-dependencies.test.ts

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ class PackageDependencyExtractor {
99
dependencyMap: Map<string, Set<string>> = new Map();
1010
artifactMap: Map<string, Set<string>> = new Map();
1111
basePackageDependencyMap: Map<string, Set<string>> = new Map();
12+
// Add property to track library counts
13+
libraryCounts = {
14+
struts: 0,
15+
commons: 0,
16+
log4j: 0,
17+
cryptix: 0
18+
};
1219

1320
async parseJsonlFile(filePath: string): Promise<void> {
1421
// In our tests, we don't actually read from a file
@@ -71,6 +78,9 @@ class PackageDependencyExtractor {
7178
}
7279
this.artifactMap.get(record.artifactId)!.add(sourcePackage);
7380
this.artifactMap.get(record.artifactId)!.add(targetPackage);
81+
82+
// Count specific libraries in targetClass
83+
this.countSpecificLibraries(targetClass);
7484
}
7585

7686
getPackageName(className: string): string {
@@ -174,6 +184,16 @@ class PackageDependencyExtractor {
174184
let markdownContent = '# Project Package Dependencies\n\n';
175185
markdownContent += 'This document lists all base packages that the project depends on.\n\n';
176186

187+
// Add section for specific library counts
188+
markdownContent += '## Specific Library Counts\n\n';
189+
markdownContent += 'These counts represent the number of dependencies where the `targetClass` field in the JSONL data contains each specific library name. This helps quantify how many times your application code depends on classes from these libraries, which is useful for identifying vulnerability exposure.\n\n';
190+
markdownContent += '| Library | Count |\n';
191+
markdownContent += '|---------|-------|\n';
192+
markdownContent += `| Struts | ${this.libraryCounts.struts} |\n`;
193+
markdownContent += `| Commons | ${this.libraryCounts.commons} |\n`;
194+
markdownContent += `| Log4j | ${this.libraryCounts.log4j} |\n`;
195+
markdownContent += `| Cryptix | ${this.libraryCounts.cryptix} |\n\n`;
196+
177197
// List all base packages
178198
markdownContent += '## Base Packages\n\n';
179199

@@ -267,6 +287,28 @@ class PackageDependencyExtractor {
267287
// Use fs.writeFileSync to write the output
268288
fs.writeFileSync(outputFile, markdownContent);
269289
}
290+
291+
// Method to count instances of specific libraries
292+
countSpecificLibraries(targetClass: string): void {
293+
// Check for each specific library in the targetClass
294+
if (targetClass.toLowerCase().includes('struts')) {
295+
this.libraryCounts.struts++;
296+
}
297+
if (targetClass.toLowerCase().includes('commons')) {
298+
this.libraryCounts.commons++;
299+
}
300+
if (targetClass.toLowerCase().includes('log4j')) {
301+
this.libraryCounts.log4j++;
302+
}
303+
if (targetClass.toLowerCase().includes('cryptix')) {
304+
this.libraryCounts.cryptix++;
305+
}
306+
}
307+
308+
// Getter for library counts (useful for testing)
309+
getLibraryCounts() {
310+
return this.libraryCounts;
311+
}
270312
}
271313

272314
// Create a mock for fs module
@@ -616,4 +658,94 @@ describe('PackageDependencyExtractor', () => {
616658
process.env.NODE_ENV = originalNodeEnv;
617659
});
618660
});
661+
});
662+
663+
// Add tests for library counts
664+
describe('countSpecificLibraries', () => {
665+
test('should count struts in targetClass', () => {
666+
const extractor = new PackageDependencyExtractor();
667+
extractor.countSpecificLibraries('org.apache.struts.actions.Action');
668+
expect(extractor.libraryCounts.struts).toBe(1);
669+
});
670+
671+
test('should count commons in targetClass', () => {
672+
const extractor = new PackageDependencyExtractor();
673+
extractor.countSpecificLibraries('org.apache.commons.lang.StringUtils');
674+
expect(extractor.libraryCounts.commons).toBe(1);
675+
});
676+
677+
test('should count log4j in targetClass', () => {
678+
const extractor = new PackageDependencyExtractor();
679+
extractor.countSpecificLibraries('org.apache.log4j.Logger');
680+
expect(extractor.libraryCounts.log4j).toBe(1);
681+
});
682+
683+
test('should count cryptix in targetClass', () => {
684+
const extractor = new PackageDependencyExtractor();
685+
extractor.countSpecificLibraries('cryptix.provider.Cipher');
686+
expect(extractor.libraryCounts.cryptix).toBe(1);
687+
});
688+
689+
test('should handle case insensitivity', () => {
690+
const extractor = new PackageDependencyExtractor();
691+
extractor.countSpecificLibraries('org.apache.STRUTS.Action');
692+
extractor.countSpecificLibraries('org.apache.COMMONS.FileUtils');
693+
extractor.countSpecificLibraries('org.apache.LOG4J.Logger');
694+
extractor.countSpecificLibraries('CRYPTIX.provider.Cipher');
695+
696+
expect(extractor.libraryCounts.struts).toBe(1);
697+
expect(extractor.libraryCounts.commons).toBe(1);
698+
expect(extractor.libraryCounts.log4j).toBe(1);
699+
expect(extractor.libraryCounts.cryptix).toBe(1);
700+
});
701+
702+
test('should handle multiple libraries in one targetClass', () => {
703+
const extractor = new PackageDependencyExtractor();
704+
extractor.countSpecificLibraries('org.apache.struts.commons.util');
705+
706+
expect(extractor.libraryCounts.struts).toBe(1);
707+
expect(extractor.libraryCounts.commons).toBe(1);
708+
expect(extractor.libraryCounts.log4j).toBe(0);
709+
expect(extractor.libraryCounts.cryptix).toBe(0);
710+
});
711+
712+
test('should increment counts correctly for multiple calls', () => {
713+
const extractor = new PackageDependencyExtractor();
714+
extractor.countSpecificLibraries('org.apache.struts.Action');
715+
extractor.countSpecificLibraries('org.apache.struts.actions.DispatchAction');
716+
extractor.countSpecificLibraries('org.apache.commons.lang.StringUtils');
717+
extractor.countSpecificLibraries('org.apache.commons.io.FileUtils');
718+
719+
expect(extractor.libraryCounts.struts).toBe(2);
720+
expect(extractor.libraryCounts.commons).toBe(2);
721+
});
722+
});
723+
724+
// Add test for processRecord with library counting
725+
test('should count libraries when processing a record', () => {
726+
const extractor = new PackageDependencyExtractor();
727+
const record = {
728+
appSetName: 'TestApp',
729+
applicationName: 'TestApp',
730+
artifactFileName: 'test.jar',
731+
artifactId: 'test',
732+
artifactGroup: 'com.test',
733+
artifactVersion: '1.0.0',
734+
sourceClass: 'com.test.TestClass',
735+
sourceMethod: 'testMethod',
736+
targetClass: 'org.apache.struts.Action',
737+
targetMethod: 'execute'
738+
};
739+
740+
extractor.processRecord(record);
741+
expect(extractor.libraryCounts.struts).toBe(1);
742+
743+
// Process another record with a different library
744+
const record2 = {
745+
...record,
746+
targetClass: 'org.apache.commons.lang.StringUtils'
747+
};
748+
749+
extractor.processRecord(record2);
750+
expect(extractor.libraryCounts.commons).toBe(1);
619751
});

0 commit comments

Comments
 (0)