From 423277f21e08b92fb83d7f391c6cc0e9c34f34f9 Mon Sep 17 00:00:00 2001 From: Shawn Hurley Date: Tue, 26 Mar 2024 16:08:49 -0400 Subject: [PATCH] :bug: Adding parsing of non WEB-INF classes as dependencies (#553) fixes #533 Signed-off-by: Shawn Hurley --- provider/internal/java/dependency.go | 33 ++++++++++++++++++++ provider/internal/java/util.go | 45 ++++++++++++++++++++++++++-- 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/provider/internal/java/dependency.go b/provider/internal/java/dependency.go index 38ba7633..390dca5f 100644 --- a/provider/internal/java/dependency.go +++ b/provider/internal/java/dependency.go @@ -323,6 +323,7 @@ func (p *javaServiceClient) discoverDepsFromJars(path string, ll map[uri.URI][]k depToLabels: p.depToLabels, m2RepoPath: getMavenLocalRepoPath(p.mvnSettingsFile), seen: map[string]bool{}, + initialPath: path, } filepath.WalkDir(path, w.walkDirForJar) } @@ -331,6 +332,7 @@ type walker struct { deps map[uri.URI][]provider.DepDAGItem depToLabels map[string]*depLabelItem m2RepoPath string + initialPath string seen map[string]bool } @@ -370,6 +372,37 @@ func (w *walker) walkDirForJar(path string, info fs.DirEntry, err error) error { }, } } + if strings.HasSuffix(info.Name(), ".class") { + // If the class is in WEB-INF we assume this is apart of the application + relPath, _ := filepath.Rel(w.initialPath, path) + relPath = filepath.Dir(relPath) + if strings.Contains(relPath, "WEB-INF") { + return nil + } + if _, ok := w.seen[relPath]; ok { + return nil + } + d := provider.Dep{ + Name: info.Name(), + } + artifact, _ := toFilePathDependency(context.Background(), filepath.Join(relPath, info.Name())) + if (artifact != javaArtifact{}) { + d.Name = fmt.Sprintf("%s.%s", artifact.GroupId, artifact.ArtifactId) + d.Version = artifact.Version + d.Labels = addDepLabels(w.depToLabels, d.Name) + d.ResolvedIdentifier = artifact.sha1 + // when we can successfully get javaArtifact from a jar + // we added it to the pom and it should be in m2Repo path + d.FileURIPrefix = fmt.Sprintf("file://%s", filepath.Join("java-project", "src", "main", + strings.Replace(artifact.GroupId, ".", "/", -1), artifact.ArtifactId)) + } + w.deps[uri.URI(filepath.Join(relPath))] = []provider.DepDAGItem{ + { + Dep: d, + }, + } + w.seen[relPath] = true + } return nil } diff --git a/provider/internal/java/util.go b/provider/internal/java/util.go index e1ad9064..d8bb0f75 100644 --- a/provider/internal/java/util.go +++ b/provider/internal/java/util.go @@ -285,9 +285,13 @@ func explode(ctx context.Context, log logr.Logger, archivePath, projectPath stri if _, err := io.Copy(dstFile, archiveFile); err != nil { return "", decompileJobs, dependencies, err } + seenDirArtificat := map[string]interface{}{} switch { - // when it's a .class file, decompile it into java project - case strings.HasSuffix(f.Name, ClassFile): + // when it's a .class file and it is in the web-inf, decompile it into java project + // This is the users code. + case strings.HasSuffix(f.Name, ClassFile) && + (strings.Contains(f.Name, "WEB-INF") || strings.Contains(f.Name, "META-INF")): + // full path in the java project for the decompd file destPath := filepath.Join( projectPath, "src", "main", "java", @@ -302,6 +306,30 @@ func explode(ctx context.Context, log logr.Logger, archivePath, projectPath stri packaging: ClassFile, }, }) + // when it's a .class file and it is not in the web-inf, decompile it into java project + // This is some dependency that is not packaged as dependency. + case strings.HasSuffix(f.Name, ClassFile) && + !(strings.Contains(f.Name, "WEB-INF") || strings.Contains(f.Name, "META-INF")): + destPath := filepath.Join( + projectPath, "src", "main", "java", + strings.Replace(filePath, destDir, "", -1)) + destPath = strings.TrimSuffix(destPath, ClassFile) + ".java" + decompileJobs = append(decompileJobs, decompileJob{ + inputPath: filePath, + outputPath: destPath, + artifact: javaArtifact{ + packaging: ClassFile, + }, + }) + if _, ok := seenDirArtificat[filepath.Dir(f.Name)]; !ok { + dep, err := toFilePathDependency(ctx, f.Name) + if err != nil { + log.V(8).Error(err, "error getting dependcy for path", "path", destPath) + continue + } + dependencies = append(dependencies, dep) + seenDirArtificat[filepath.Dir(f.Name)] = nil + } // when it's a java file, it's already decompiled, move it to project path case strings.HasSuffix(f.Name, JavaFile): destPath := filepath.Join( @@ -558,3 +586,16 @@ func constructArtifactFromSHA(jarFile string) (javaArtifact, error) { } return dep, fmt.Errorf("failed to construct artifact from maven lookup") } + +func toFilePathDependency(ctx context.Context, filePath string) (javaArtifact, error) { + dep := javaArtifact{} + // Move up one level to the artifact. we are assuming that we get the full class file here. + // For instance the dir /org/springframework/boot/loader/jar/Something.class. + // in this cass the artificat is: Group: org.springframework.boot.loader, Artifact: Jar + dir := filepath.Dir(filePath) + dep.ArtifactId = filepath.Base(dir) + dep.GroupId = strings.Replace(filepath.Dir(dir), "/", ".", -1) + dep.Version = "0.0.0" + return dep, nil + +}