pkg/util/camel/camel_dependencies.go (231 lines of code) (raw):
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package camel
import (
"fmt"
"io"
"strings"
v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
"github.com/apache/camel-k/v2/pkg/util/jitpack"
"github.com/apache/camel-k/v2/pkg/util/maven"
"github.com/rs/xid"
)
// NormalizeDependency converts different forms of camel dependencies
// -- `camel-xxx`, `camel-quarkus-xxx`, and `camel-quarkus:xxx` --
// into the unified form `camel:xxx`.
func NormalizeDependency(dependency string) string {
newDep := dependency
switch {
case strings.HasPrefix(newDep, "camel-quarkus-"):
newDep = "camel:" + strings.TrimPrefix(dependency, "camel-quarkus-")
case strings.HasPrefix(newDep, "camel-quarkus:"):
newDep = "camel:" + strings.TrimPrefix(dependency, "camel-quarkus:")
case strings.HasPrefix(newDep, "camel-k-"):
newDep = "camel-k:" + strings.TrimPrefix(dependency, "camel-k-")
case strings.HasPrefix(newDep, "camel-k:"):
// do nothing
case strings.HasPrefix(newDep, "camel-"):
newDep = "camel:" + strings.TrimPrefix(dependency, "camel-")
}
return newDep
}
// ValidateDependency validates a dependency against Camel catalog.
// It only shows warning and does not throw error in case the Catalog is just not complete,
// and we don't want to let it stop the process.
func ValidateDependency(catalog *RuntimeCatalog, dependency string, out io.Writer) {
if err := ValidateDependencyE(catalog, dependency); err != nil {
fmt.Fprintf(out, "Warning: %s\n", err.Error())
}
switch {
case strings.HasPrefix(dependency, "mvn:org.apache.camel:"):
component := strings.Split(dependency, ":")[2]
fmt.Fprintf(out, "Warning: do not use %s. Use %s instead\n",
dependency, NormalizeDependency(component))
case strings.HasPrefix(dependency, "mvn:org.apache.camel.quarkus:"):
component := strings.Split(dependency, ":")[2]
fmt.Fprintf(out, "Warning: do not use %s. Use %s instead\n",
dependency, NormalizeDependency(component))
}
}
// ValidateDependencyE validates a dependency against Camel catalog and throws error
// in case it does not exist in the catalog.
func ValidateDependencyE(catalog *RuntimeCatalog, dependency string) error {
var artifact string
switch {
case strings.HasPrefix(dependency, "camel:"):
artifact = strings.TrimPrefix(dependency, "camel:")
case strings.HasPrefix(dependency, "camel-quarkus:"):
artifact = strings.TrimPrefix(dependency, "camel-quarkus:")
case strings.HasPrefix(dependency, "camel-"):
artifact = dependency
}
if artifact == "" {
return nil
}
if ok := catalog.IsValidArtifact(artifact); !ok {
return fmt.Errorf("dependency %s not found in Camel catalog", dependency)
}
return nil
}
// ValidateDependenciesE validates dependencies against Camel catalog and throws error
// in case it does not exist in the catalog.
func ValidateDependenciesE(catalog *RuntimeCatalog, dependencies []string) error {
for _, dependency := range dependencies {
if err := ValidateDependencyE(catalog, dependency); err != nil {
return err
}
}
return nil
}
// ManageIntegrationDependencies sets up all the required dependencies for the given Maven project.
func ManageIntegrationDependencies(project *maven.Project, dependencies []string, catalog *RuntimeCatalog) error {
// Add dependencies from build
if err := addDependencies(project, dependencies, catalog); err != nil {
return err
}
// Add dependencies from catalog
addDependenciesFromCatalog(project, catalog)
// Post process dependencies
postProcessDependencies(project, catalog)
return nil
}
func addDependencies(project *maven.Project, dependencies []string, catalog *RuntimeCatalog) error {
for _, d := range dependencies {
switch {
case strings.HasPrefix(d, "bom:"):
if err := addBOM(project, d); err != nil {
return err
}
case strings.HasPrefix(d, "camel:"):
addCamelComponent(project, catalog, d)
case strings.HasPrefix(d, "camel-k:"):
addCamelKComponent(project, d)
case strings.HasPrefix(d, "camel-quarkus:"):
addCamelQuarkusComponent(project, d)
case strings.HasPrefix(d, "mvn:"):
addMavenDependency(project, d)
default:
if err := addJitPack(project, d); err != nil {
return err
}
}
}
return nil
}
func addBOM(project *maven.Project, dependency string) error {
gav := strings.TrimPrefix(dependency, "bom:")
d, err := maven.ParseGAV(gav)
if err != nil {
return err
}
project.DependencyManagement.Dependencies = append(project.DependencyManagement.Dependencies,
maven.Dependency{
GroupID: d.GroupID,
ArtifactID: d.ArtifactID,
Version: d.Version,
Type: "pom",
Scope: "import",
})
return nil
}
func addCamelComponent(project *maven.Project, catalog *RuntimeCatalog, dependency string) {
artifactID := strings.TrimPrefix(dependency, "camel:")
if catalog != nil && catalog.Runtime.Provider.IsQuarkusBased() {
if !strings.HasPrefix(artifactID, "camel-") {
artifactID = "camel-quarkus-" + artifactID
}
project.AddDependencyGAV("org.apache.camel.quarkus", artifactID, "")
} else {
if !strings.HasPrefix(artifactID, "camel-") {
artifactID = "camel-" + artifactID
}
project.AddDependencyGAV("org.apache.camel", artifactID, "")
}
}
func addCamelKComponent(project *maven.Project, dependency string) {
artifactID := strings.TrimPrefix(dependency, "camel-k:")
if !strings.HasPrefix(artifactID, "camel-k-") {
artifactID = "camel-k-" + artifactID
}
project.AddDependencyGAV("org.apache.camel.k", artifactID, "")
}
func addCamelQuarkusComponent(project *maven.Project, dependency string) {
artifactID := strings.TrimPrefix(dependency, "camel-quarkus:")
if !strings.HasPrefix(artifactID, "camel-quarkus-") {
artifactID = "camel-quarkus-" + artifactID
}
project.AddDependencyGAV("org.apache.camel.quarkus", artifactID, "")
}
func addMavenDependency(project *maven.Project, dependency string) {
gav := strings.TrimPrefix(dependency, "mvn:")
project.AddEncodedDependencyGAV(gav)
}
func addJitPack(project *maven.Project, dependency string) error {
dep := jitpack.ToDependency(dependency)
if dep == nil {
return fmt.Errorf("unknown dependency type: %s", dependency)
}
project.AddDependency(*dep)
addRepo := true
for _, repo := range project.Repositories {
if repo.URL == jitpack.RepoURL {
addRepo = false
break
}
}
if addRepo {
project.Repositories = append(project.Repositories, v1.Repository{
ID: "jitpack.io-" + xid.New().String(),
URL: jitpack.RepoURL,
Releases: v1.RepositoryPolicy{
Enabled: true,
ChecksumPolicy: "fail",
},
Snapshots: v1.RepositoryPolicy{
Enabled: true,
ChecksumPolicy: "fail",
},
})
}
return nil
}
func addDependenciesFromCatalog(project *maven.Project, catalog *RuntimeCatalog) {
deps := make([]maven.Dependency, len(project.Dependencies))
copy(deps, project.Dependencies)
for _, d := range deps {
if a, ok := catalog.Artifacts[d.ArtifactID]; ok {
for _, dep := range a.Dependencies {
md := maven.Dependency{
GroupID: dep.GroupID,
ArtifactID: dep.ArtifactID,
Type: dep.Type,
Classifier: dep.Classifier,
}
project.AddDependency(md)
for _, e := range dep.Exclusions {
me := maven.Exclusion{
GroupID: e.GroupID,
ArtifactID: e.ArtifactID,
}
project.AddDependencyExclusion(md, me)
}
}
}
}
}
func postProcessDependencies(project *maven.Project, catalog *RuntimeCatalog) {
deps := make([]maven.Dependency, len(project.Dependencies))
copy(deps, project.Dependencies)
for _, d := range deps {
if a, ok := catalog.Artifacts[d.ArtifactID]; ok {
md := maven.Dependency{
GroupID: a.GroupID,
ArtifactID: a.ArtifactID,
}
for _, e := range a.Exclusions {
me := maven.Exclusion{
GroupID: e.GroupID,
ArtifactID: e.ArtifactID,
}
project.AddDependencyExclusion(md, me)
}
}
}
}
// SanitizeIntegrationDependencies --.
func SanitizeIntegrationDependencies(dependencies []maven.Dependency) error {
for i := range dependencies {
dep := dependencies[i]
// It may be externalized into runtime provider specific steps
switch dep.GroupID {
case "org.apache.camel":
fallthrough
case "org.apache.camel.k":
fallthrough
case "org.apache.camel.quarkus":
//
// Remove the version so we force using the one configured by the bom
//
dependencies[i].Version = ""
}
}
return nil
}