Files
syft/syft/pkg/cataloger/java/internal/maven/config.go
T
2024-10-23 11:17:34 -04:00

95 lines
3.3 KiB
Go

package maven
import (
"encoding/xml"
"fmt"
"io"
"net/url"
"os"
"path/filepath"
"strings"
"github.com/mitchellh/go-homedir"
"github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/log"
)
const mavenBaseURL = "https://repo1.maven.org/maven2"
type Config struct {
// UseNetwork instructs the maven resolver to use network operations to resolve maven artifacts
UseNetwork bool `yaml:"use-network" json:"use-network" mapstructure:"use-network"`
// Repositories are the set of remote repositories the network resolution should use
Repositories []string `yaml:"maven-repositories" json:"maven-repositories" mapstructure:"maven-repositories"`
// UseLocalRepository instructs the maven resolver to look in the host maven cache, usually ~/.m2/repository
UseLocalRepository bool `yaml:"use-maven-local-repository" json:"use-maven-local-repository" mapstructure:"use-maven-local-repository"`
// LocalRepositoryDir is an alternate directory to use to look up the local repository
LocalRepositoryDir string `yaml:"maven-local-repository-dir" json:"maven-local-repository-dir" mapstructure:"maven-local-repository-dir"`
// MaxParentRecursiveDepth allows for a maximum depth to use when recursively resolving parent poms and other information, 0 disables any maximum
MaxParentRecursiveDepth int `yaml:"max-parent-recursive-depth" json:"max-parent-recursive-depth" mapstructure:"max-parent-recursive-depth"`
}
func DefaultConfig() Config {
return Config{
UseNetwork: false,
Repositories: []string{mavenBaseURL},
UseLocalRepository: false,
LocalRepositoryDir: defaultMavenLocalRepoDir(),
MaxParentRecursiveDepth: 0, // unlimited
}
}
// defaultMavenLocalRepoDir gets default location of the Maven local repository, generally at <USER HOME DIR>/.m2/repository
func defaultMavenLocalRepoDir() string {
homeDir, err := homedir.Dir()
if err != nil {
return ""
}
mavenHome := filepath.Join(homeDir, ".m2")
settingsXML := filepath.Join(mavenHome, "settings.xml")
settings, err := os.Open(settingsXML)
if err == nil && settings != nil {
defer internal.CloseAndLogError(settings, settingsXML)
localRepository := getSettingsXMLLocalRepository(settings)
if localRepository != "" {
return localRepository
}
}
return filepath.Join(mavenHome, "repository")
}
// getSettingsXMLLocalRepository reads the provided settings.xml and parses the localRepository, if present
func getSettingsXMLLocalRepository(settingsXML io.Reader) string {
type settings struct {
LocalRepository string `xml:"localRepository"`
}
s := settings{}
err := xml.NewDecoder(settingsXML).Decode(&s)
if err != nil {
log.WithFields("error", err).Debug("unable to read maven settings.xml")
}
return s.LocalRepository
}
// remotePomURL returns a URL to download a POM from a remote repository
func remotePomURL(repoURL, groupID, artifactID, version string) (requestURL string, err error) {
// groupID needs to go from maven.org -> maven/org
urlPath := strings.Split(groupID, ".")
artifactPom := fmt.Sprintf("%s-%s.pom", artifactID, version)
urlPath = append(urlPath, artifactID, version, artifactPom)
// ex: https://repo1.maven.org/maven2/groupID/artifactID/artifactPom
requestURL, err = url.JoinPath(repoURL, urlPath...)
if err != nil {
return requestURL, fmt.Errorf("could not construct maven url: %w", err)
}
return requestURL, err
}