diff --git a/external-providers/java-external-provider/pkg/java_external_provider/provider.go b/external-providers/java-external-provider/pkg/java_external_provider/provider.go index 4a93eb1e..d052a2a3 100644 --- a/external-providers/java-external-provider/pkg/java_external_provider/provider.go +++ b/external-providers/java-external-provider/pkg/java_external_provider/provider.go @@ -44,6 +44,7 @@ const ( MVN_SETTINGS_FILE_INIT_OPTION = "mavenSettingsFile" GLOBAL_SETTINGS_INIT_OPTION = "mavenCacheDir" JVM_MAX_MEM_INIT_OPTION = "jvmMaxMem" + FERN_FLOWER_INIT_OPTION = "fernFlowerPath" ) // Rule Location to location that the bundle understands @@ -255,6 +256,10 @@ func (p *javaProvider) Init(ctx context.Context, log logr.Logger, config provide if !ok || lspServerPath == "" { return nil, additionalBuiltinConfig, fmt.Errorf("invalid lspServerPath provided, unable to init java provider") } + fernflower, ok := config.ProviderSpecificConfig[FERN_FLOWER_INIT_OPTION].(string) + if !ok { + fernflower = "/bin/fernflower.jar" + } isBinary := false var returnErr error @@ -320,7 +325,7 @@ func (p *javaProvider) Init(ctx context.Context, log logr.Logger, config provide extension := strings.ToLower(path.Ext(config.Location)) switch extension { case JavaArchive, WebArchive, EnterpriseArchive: - depLocation, sourceLocation, err := decompileJava(ctx, log, + depLocation, sourceLocation, err := decompileJava(ctx, log, fernflower, config.Location, getMavenLocalRepoPath(mavenSettingsFile)) if err != nil { cancelFunc() @@ -410,13 +415,13 @@ func (p *javaProvider) Init(ctx context.Context, log logr.Logger, config provide // we need to do this for jdtls to correctly recognize source attachment for dep switch svcClient.GetBuildTool() { case maven: - err := resolveSourcesJarsForMaven(ctx, log, config.Location, mavenSettingsFile) + err := resolveSourcesJarsForMaven(ctx, log, fernflower, config.Location, mavenSettingsFile) if err != nil { // TODO (pgaikwad): should we ignore this failure? log.Error(err, "failed to resolve maven sources jar for location", "location", config.Location) } case gradle: - err = resolveSourcesJarsForGradle(ctx, log, config.Location, mavenSettingsFile, &svcClient) + err = resolveSourcesJarsForGradle(ctx, log, fernflower, config.Location, mavenSettingsFile, &svcClient) if err != nil { log.Error(err, "failed to resolve gradle sources jar for location", "location", config.Location) } @@ -456,7 +461,7 @@ func (p *javaProvider) Init(ctx context.Context, log logr.Logger, config provide return &svcClient, additionalBuiltinConfig, returnErr } -func resolveSourcesJarsForGradle(ctx context.Context, log logr.Logger, location string, _ string, svc *javaServiceClient) error { +func resolveSourcesJarsForGradle(ctx context.Context, log logr.Logger, fernflower, location string, _ string, svc *javaServiceClient) error { ctx, span := tracing.StartNewSpan(ctx, "resolve-sources") defer span.End() @@ -555,7 +560,7 @@ func resolveSourcesJarsForGradle(ctx context.Context, log logr.Logger, location outputPath: filepath.Join(filepath.Dir(artifactPath), "decompiled", jarName), }) } - err = decompile(ctx, log, alwaysDecompileFilter(true), 10, decompileJobs, "") + err = decompile(ctx, log, alwaysDecompileFilter(true), 10, decompileJobs, fernflower, "") if err != nil { return err } @@ -686,7 +691,7 @@ func (j *javaProvider) GetLocation(ctx context.Context, dep konveyor.Dep, file s // resolveSourcesJarsForMaven for a given source code location, runs maven to find // deps that don't have sources attached and decompiles them -func resolveSourcesJarsForMaven(ctx context.Context, log logr.Logger, location, mavenSettings string) error { +func resolveSourcesJarsForMaven(ctx context.Context, log logr.Logger, fernflower, location, mavenSettings string) error { // TODO (pgaikwad): when we move to external provider, inherit context from parent ctx, span := tracing.StartNewSpan(ctx, "resolve-sources") defer span.End() @@ -735,7 +740,7 @@ func resolveSourcesJarsForMaven(ctx context.Context, log logr.Logger, location, m2Repo, groupDirs, artifactDirs, artifact.Version, "decompiled", jarName), }) } - err = decompile(ctx, log, alwaysDecompileFilter(true), 10, decompileJobs, "") + err = decompile(ctx, log, alwaysDecompileFilter(true), 10, decompileJobs, fernflower, "") if err != nil { return err } diff --git a/external-providers/java-external-provider/pkg/java_external_provider/util.go b/external-providers/java-external-provider/pkg/java_external_provider/util.go index dcff629a..5d1b5804 100644 --- a/external-providers/java-external-provider/pkg/java_external_provider/util.go +++ b/external-providers/java-external-provider/pkg/java_external_provider/util.go @@ -84,7 +84,7 @@ type decompileJob struct { // decompile decompiles files submitted via a list of decompileJob concurrently // if a .class file is encountered, it will be decompiled to output path right away // if a .jar file is encountered, it will be decompiled as a whole, then exploded to project path -func decompile(ctx context.Context, log logr.Logger, filter decompileFilter, workerCount int, jobs []decompileJob, projectPath string) error { +func decompile(ctx context.Context, log logr.Logger, filter decompileFilter, workerCount int, jobs []decompileJob, fernflower, projectPath string) error { wg := &sync.WaitGroup{} jobChan := make(chan decompileJob) @@ -119,7 +119,7 @@ func decompile(ctx context.Context, log logr.Logger, filter decompileFilter, wor java := filepath.Join(os.Getenv("JAVA_HOME"), "bin", "java") // -mpm (max processing method) is required to keep decomp time low cmd := exec.CommandContext( - jobCtx, java, "-jar", "/bin/fernflower.jar", "-mpm=30", job.inputPath, outputPathDir) + jobCtx, java, "-jar", fernflower, "-mpm=30", job.inputPath, outputPathDir) err := cmd.Run() if err != nil { log.V(5).Error(err, "failed to decompile file", "file", job.inputPath, job.outputPath) @@ -159,7 +159,7 @@ func decompile(ctx context.Context, log logr.Logger, filter decompileFilter, wor // decompileJava unpacks archive at archivePath, decompiles all .class files in it // creates new java project and puts the java files in the tree of the project // returns path to exploded archive, path to java project, and an error when encountered -func decompileJava(ctx context.Context, log logr.Logger, archivePath string, m2RepoPath string) (explodedPath, projectPath string, err error) { +func decompileJava(ctx context.Context, log logr.Logger, fernflower, archivePath string, m2RepoPath string) (explodedPath, projectPath string, err error) { ctx, span := tracing.StartNewSpan(ctx, "decompile") defer span.End() @@ -180,7 +180,7 @@ func decompileJava(ctx context.Context, log logr.Logger, archivePath string, m2R } log.V(5).Info("created java project", "path", projectPath) - err = decompile(ctx, log, decompFilter, 10, decompJobs, projectPath) + err = decompile(ctx, log, decompFilter, 10, decompJobs, fernflower, projectPath) if err != nil { log.Error(err, "failed to decompile", "path", archivePath) return "", "", err