You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2020/03/11 21:00:24 UTC

[camel-k] 02/02: refactor source code inspectors to avoid using redgexp for markup languages

This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 25a4f3d30676f41e3db42ceadda19f55c28f87cc
Author: lburgazzoli <lb...@gmail.com>
AuthorDate: Wed Mar 11 20:33:15 2020 +0100

    refactor source code inspectors to avoid using redgexp for markup languages
---
 examples/RestWithUndertow.java             |  41 -------
 pkg/metadata/http.go                       | 102 ----------------
 pkg/metadata/metadata.go                   |  37 +++---
 pkg/metadata/metadata_dependencies_test.go | 185 ++++++++++++++++++++++++++---
 pkg/metadata/metadata_http_test.go         |  20 ++--
 pkg/metadata/types.go                      |  17 ---
 pkg/trait/knative_service.go               |   4 +-
 pkg/trait/service.go                       |   2 +-
 pkg/util/source/inspector.go               | 173 ++++++++++++++++++++++-----
 pkg/util/source/inspector_groovy.go        |   5 +
 pkg/util/source/inspector_java_script.go   |   3 +
 pkg/util/source/inspector_java_source.go   |   3 +
 pkg/util/source/inspector_kotlin.go        |   5 +
 pkg/util/source/inspector_xml.go           |   4 +
 pkg/util/source/inspector_yaml.go          |   5 +-
 pkg/util/source/types.go                   |  16 +++
 16 files changed, 384 insertions(+), 238 deletions(-)

diff --git a/examples/RestWithUndertow.java b/examples/RestWithUndertow.java
deleted file mode 100644
index 63090a6..0000000
--- a/examples/RestWithUndertow.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-
-//
-// To run this integrations use:
-//
-//     kamel run --name=rest-with-undertow --dependency=camel-rest --dependency=camel-undertow examples/RestWithUndertow.java
-//
-import org.apache.camel.Exchange;
-
-public class RestWithUndertow extends org.apache.camel.builder.RouteBuilder {
-    @Override
-    public void configure() throws Exception {
-        restConfiguration()
-            .component("undertow")
-            .host("0.0.0.0")
-            .port("8080");
-
-        rest()
-            .get("/hello")
-            .to("direct:hello");
-
-        from("direct:hello")
-            .setHeader(Exchange.CONTENT_TYPE, constant("text/plain"))
-            .transform().simple("Hello World");
-    }
-}
diff --git a/pkg/metadata/http.go b/pkg/metadata/http.go
deleted file mode 100644
index be56808..0000000
--- a/pkg/metadata/http.go
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
-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 metadata
-
-import (
-	"regexp"
-	"strings"
-
-	"github.com/apache/camel-k/pkg/util/camel"
-
-	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
-)
-
-var restIndicator = regexp.MustCompile(`.*rest\s*\([^)]*\).*`)
-var xmlRestIndicator = regexp.MustCompile(`.*<\s*rest\s+[^>]*>.*`)
-
-// requiresHTTPService returns true if the integration needs to expose itself through HTTP
-func requiresHTTPService(catalog *camel.RuntimeCatalog, source v1.SourceSpec, fromURIs []string) bool {
-	if hasRestIndicator(source) {
-		return true
-	}
-	return containsHTTPURIs(catalog, fromURIs)
-}
-
-// hasOnlyPassiveEndpoints returns true if the integration has no endpoint that needs to remain always active
-func hasOnlyPassiveEndpoints(catalog *camel.RuntimeCatalog, _ v1.SourceSpec, fromURIs []string) bool {
-	passivePlusHTTP := make(map[string]bool)
-	catalog.VisitSchemes(func(id string, scheme v1.CamelScheme) bool {
-		if scheme.HTTP || scheme.Passive {
-			passivePlusHTTP[id] = true
-		}
-
-		return true
-	})
-
-	return containsOnlyURIsIn(fromURIs, passivePlusHTTP)
-}
-
-func containsHTTPURIs(catalog *camel.RuntimeCatalog, fromURI []string) bool {
-	for _, uri := range fromURI {
-		prefix := getURIPrefix(uri)
-		scheme, ok := catalog.GetScheme(prefix)
-
-		if !ok {
-			// scheme dees not exists
-			continue
-		}
-
-		if scheme.HTTP {
-			return true
-		}
-	}
-
-	return false
-}
-
-func containsOnlyURIsIn(fromURI []string, allowed map[string]bool) bool {
-	for _, uri := range fromURI {
-		prefix := getURIPrefix(uri)
-		if enabled, ok := allowed[prefix]; !ok || !enabled {
-			return false
-		}
-	}
-	return true
-}
-
-func getURIPrefix(uri string) string {
-	parts := strings.SplitN(uri, ":", 2)
-	if len(parts) > 0 {
-		return parts[0]
-	}
-	return ""
-}
-
-func hasRestIndicator(source v1.SourceSpec) bool {
-	pat := getRestIndicatorRegexpsForLanguage(source.InferLanguage())
-	return pat.MatchString(source.Content)
-}
-
-func getRestIndicatorRegexpsForLanguage(language v1.Language) *regexp.Regexp {
-	switch language {
-	case v1.LanguageXML:
-		return xmlRestIndicator
-	default:
-		return restIndicator
-	}
-}
diff --git a/pkg/metadata/metadata.go b/pkg/metadata/metadata.go
index 9f9b53e..2c8dd8e 100644
--- a/pkg/metadata/metadata.go
+++ b/pkg/metadata/metadata.go
@@ -31,17 +31,19 @@ import (
 // ExtractAll returns metadata information from all listed source codes
 func ExtractAll(catalog *camel.RuntimeCatalog, sources []v1.SourceSpec) IntegrationMetadata {
 	// neutral metadata
-	meta := NewIntegrationMetadata()
+	meta := src.NewMetadata()
 	meta.PassiveEndpoints = true
-	meta.RequiresHTTPService = false
+	meta.ExposesHTTPServices = false
 
 	for _, source := range sources {
-		meta = merge(meta, Extract(catalog, source))
+		meta = merge(meta, Extract(catalog, source).Metadata)
+	}
+	return IntegrationMetadata{
+		Metadata: meta,
 	}
-	return meta
 }
 
-func merge(m1 IntegrationMetadata, m2 IntegrationMetadata) IntegrationMetadata {
+func merge(m1 src.Metadata, m2 src.Metadata) src.Metadata {
 	d := strset.Union(m1.Dependencies, m2.Dependencies)
 
 	f := make([]string, 0, len(m1.FromURIs)+len(m2.FromURIs))
@@ -52,13 +54,11 @@ func merge(m1 IntegrationMetadata, m2 IntegrationMetadata) IntegrationMetadata {
 	t = append(t, m1.ToURIs...)
 	t = append(t, m2.ToURIs...)
 
-	return IntegrationMetadata{
-		Metadata: src.Metadata{
-			FromURIs:     f,
-			ToURIs:       t,
-			Dependencies: d,
-		},
-		RequiresHTTPService: m1.RequiresHTTPService || m2.RequiresHTTPService,
+	return src.Metadata{
+		FromURIs:            f,
+		ToURIs:              t,
+		Dependencies:        d,
+		ExposesHTTPServices: m1.ExposesHTTPServices || m2.ExposesHTTPServices,
 		PassiveEndpoints:    m1.PassiveEndpoints && m2.PassiveEndpoints,
 	}
 }
@@ -73,15 +73,16 @@ func Extract(catalog *camel.RuntimeCatalog, source v1.SourceSpec) IntegrationMet
 
 	language := source.InferLanguage()
 
-	m := NewIntegrationMetadata()
+	meta := src.NewMetadata()
+	meta.PassiveEndpoints = true
+	meta.ExposesHTTPServices = false
 
 	// TODO: handle error
-	_ = src.InspectorForLanguage(catalog, language).Extract(source, &m.Metadata)
+	_ = src.InspectorForLanguage(catalog, language).Extract(source, &meta)
 
-	m.RequiresHTTPService = requiresHTTPService(catalog, source, m.FromURIs)
-	m.PassiveEndpoints = hasOnlyPassiveEndpoints(catalog, source, m.FromURIs)
-
-	return m
+	return IntegrationMetadata{
+		Metadata: meta,
+	}
 }
 
 // Each --
diff --git a/pkg/metadata/metadata_dependencies_test.go b/pkg/metadata/metadata_dependencies_test.go
index 1a96276..fe5c0e9 100644
--- a/pkg/metadata/metadata_dependencies_test.go
+++ b/pkg/metadata/metadata_dependencies_test.go
@@ -48,7 +48,17 @@ func TestDependenciesJavaSource(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.ElementsMatch(t, []string{"camel:activemq", "camel:amqp", "camel:log", "camel:telegram", "camel:timer", "camel:twitter"}, meta.Dependencies.List())
+	assert.ElementsMatch(
+		t,
+		[]string{
+			"camel:activemq",
+			"camel:amqp",
+			"camel:log",
+			"camel:telegram",
+			"camel:timer",
+			"camel:twitter",
+		},
+		meta.Dependencies.List())
 }
 
 func TestDependenciesJavaScript(t *testing.T) {
@@ -72,7 +82,16 @@ func TestDependenciesJavaScript(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.ElementsMatch(t, []string{"camel:activemq", "camel:amqp", "camel:log", "camel:telegram", "camel:timer"}, meta.Dependencies.List())
+	assert.ElementsMatch(
+		t,
+		[]string{
+			"camel:activemq",
+			"camel:amqp",
+			"camel:log",
+			"camel:telegram",
+			"camel:timer",
+		},
+		meta.Dependencies.List())
 }
 
 func TestDependenciesGroovy(t *testing.T) {
@@ -98,7 +117,17 @@ func TestDependenciesGroovy(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.ElementsMatch(t, []string{"camel:activemq", "camel:amqp", "camel:log", "camel:telegram", "camel:timer", "camel:twitter"}, meta.Dependencies.List())
+	assert.ElementsMatch(
+		t,
+		[]string{
+			"camel:activemq",
+			"camel:amqp",
+			"camel:log",
+			"camel:telegram",
+			"camel:timer",
+			"camel:twitter",
+		},
+		meta.Dependencies.List())
 }
 
 func TestDependencies(t *testing.T) {
@@ -180,7 +209,14 @@ func TestJacksonDependency(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.ElementsMatch(t, []string{"camel:http", "camel:jackson", "camel:log"}, meta.Dependencies.List())
+	assert.ElementsMatch(
+		t,
+		[]string{
+			"camel:http",
+			"camel:jackson",
+			"camel:log",
+		},
+		meta.Dependencies.List())
 }
 
 func TestJacksonImplicitDependency(t *testing.T) {
@@ -201,7 +237,14 @@ func TestJacksonImplicitDependency(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.ElementsMatch(t, []string{"camel:http", "camel:jackson", "camel:log"}, meta.Dependencies.List())
+	assert.ElementsMatch(
+		t,
+		[]string{
+			"camel:http",
+			"camel:jackson",
+			"camel:log",
+		},
+		meta.Dependencies.List())
 }
 
 func TestLanguageDependencies(t *testing.T) {
@@ -227,8 +270,19 @@ func TestLanguageDependencies(t *testing.T) {
 	assert.Nil(t, err)
 
 	meta := Extract(catalog, code)
-	assert.ElementsMatch(t, []string{"camel:direct", "camel:ognl", "camel:saxon", "camel:xpath",
-		"camel:jsonpath", "camel:groovy", "camel:jaxp", "camel:mvel"}, meta.Dependencies.List())
+	assert.ElementsMatch(
+		t,
+		[]string{
+			"camel:direct",
+			"camel:ognl",
+			"camel:saxon",
+			"camel:xpath",
+			"camel:jsonpath",
+			"camel:groovy",
+			"camel:xml-jaxp",
+			"camel:mvel",
+		},
+		meta.Dependencies.List())
 }
 
 func TestLanguageDependenciesTransformExpression(t *testing.T) {
@@ -250,7 +304,15 @@ func TestLanguageDependenciesTransformExpression(t *testing.T) {
 	assert.Nil(t, err)
 
 	meta := Extract(catalog, code)
-	assert.ElementsMatch(t, []string{"camel:direct", "camel:ognl", "camel:xpath", "camel:jsonpath"}, meta.Dependencies.List())
+	assert.ElementsMatch(
+		t,
+		[]string{
+			"camel:direct",
+			"camel:ognl",
+			"camel:xpath",
+			"camel:jsonpath",
+		},
+		meta.Dependencies.List())
 }
 
 func TestHystrixDependency(t *testing.T) {
@@ -273,7 +335,13 @@ func TestHystrixDependency(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.ElementsMatch(t, []string{"camel:http", "camel:hystrix", "camel:log"}, meta.Dependencies.List())
+	assert.ElementsMatch(t,
+		[]string{
+			"camel:http",
+			"camel:hystrix",
+			"camel:log",
+		},
+		meta.Dependencies.List())
 }
 
 func TestRestDependency(t *testing.T) {
@@ -296,7 +364,16 @@ func TestRestDependency(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.ElementsMatch(t, []string{"camel:http", "camel:rest", "camel:direct", "camel:log"}, meta.Dependencies.List())
+	assert.ElementsMatch(
+		t,
+		[]string{
+			"camel:http",
+			"camel:direct",
+			"camel:log",
+			"mvn:org.apache.camel/camel-rest",
+			"mvn:org.apache.camel/camel-undertow",
+		},
+		meta.Dependencies.List())
 }
 
 func TestRestWithPathDependency(t *testing.T) {
@@ -319,7 +396,15 @@ func TestRestWithPathDependency(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.ElementsMatch(t, []string{"camel:http", "camel:rest", "camel:direct", "camel:log"}, meta.Dependencies.List())
+	assert.ElementsMatch(
+		t, []string{
+			"camel:http",
+			"camel:direct",
+			"camel:log",
+			"mvn:org.apache.camel/camel-rest",
+			"mvn:org.apache.camel/camel-undertow",
+		},
+		meta.Dependencies.List())
 }
 
 func TestRestConfigurationDependency(t *testing.T) {
@@ -341,10 +426,17 @@ func TestRestConfigurationDependency(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.ElementsMatch(t, []string{"camel:http", "camel:rest", "camel:log"}, meta.Dependencies.List())
+	assert.ElementsMatch(
+		t, []string{
+			"camel:http",
+			"camel:log",
+			"mvn:org.apache.camel/camel-rest",
+			"mvn:org.apache.camel/camel-undertow",
+		},
+		meta.Dependencies.List())
 }
 
-func TestRestClosureDependency(t *testing.T) {
+func TestRestClosureDependencyGroovy(t *testing.T) {
 	code := v1.SourceSpec{
 		DataSpec: v1.DataSpec{
 			Name: "Request.groovy",
@@ -363,7 +455,45 @@ func TestRestClosureDependency(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.ElementsMatch(t, []string{"camel:http", "camel:rest", "camel:log"}, meta.Dependencies.List())
+	assert.ElementsMatch(
+		t,
+		[]string{
+			"camel:http",
+			"camel:log",
+			"mvn:org.apache.camel/camel-rest",
+			"mvn:org.apache.camel/camel-undertow",
+		},
+		meta.Dependencies.List())
+}
+
+func TestRestClosureDependencyKotlin(t *testing.T) {
+	code := v1.SourceSpec{
+		DataSpec: v1.DataSpec{
+			Name: "Request.groovy",
+			Content: `
+                rest {
+                }
+			    from("http:test")
+                    .to("log:info")
+		    `,
+		},
+		Language: v1.LanguageKotlin,
+	}
+
+	catalog, err := camel.DefaultCatalog()
+	assert.Nil(t, err)
+
+	meta := Extract(catalog, code)
+
+	assert.ElementsMatch(
+		t,
+		[]string{
+			"camel:http",
+			"camel:log",
+			"mvn:org.apache.camel/camel-rest",
+			"mvn:org.apache.camel/camel-undertow",
+		},
+		meta.Dependencies.List())
 }
 
 func TestXMLHystrixDependency(t *testing.T) {
@@ -389,7 +519,15 @@ func TestXMLHystrixDependency(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.ElementsMatch(t, []string{"camel:direct", "camel:hystrix", "camel:kafka", "camel:log"}, meta.Dependencies.List())
+	assert.ElementsMatch(
+		t,
+		[]string{
+			"camel:direct",
+			"camel:hystrix",
+			"camel:kafka",
+			"camel:log",
+		},
+		meta.Dependencies.List())
 }
 
 func TestXMLRestDependency(t *testing.T) {
@@ -419,7 +557,14 @@ func TestXMLRestDependency(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.ElementsMatch(t, []string{"camel:direct", "camel:rest", "camel:mock"}, meta.Dependencies.List())
+	assert.ElementsMatch(
+		t,
+		[]string{
+			"camel:direct",
+			"camel:rest",
+			"camel:mock",
+		},
+		meta.Dependencies.List())
 }
 
 func TestXMLLanguageDependencies(t *testing.T) {
@@ -556,7 +701,13 @@ func TestYAMLHystrixDependency(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.ElementsMatch(t, []string{"camel:direct", "camel:hystrix"}, meta.Dependencies.List())
+	assert.ElementsMatch(
+		t,
+		[]string{
+			"camel:direct",
+			"camel:hystrix",
+		},
+		meta.Dependencies.List())
 }
 
 func TestYAMLLanguageDependencies(t *testing.T) {
diff --git a/pkg/metadata/metadata_http_test.go b/pkg/metadata/metadata_http_test.go
index e89365e..97b4aea 100644
--- a/pkg/metadata/metadata_http_test.go
+++ b/pkg/metadata/metadata_http_test.go
@@ -44,7 +44,7 @@ func TestHttpJavaSource(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.True(t, meta.RequiresHTTPService)
+	assert.True(t, meta.ExposesHTTPServices)
 	assert.False(t, meta.PassiveEndpoints)
 }
 
@@ -67,7 +67,7 @@ func TestHttpOnlyJavaSource(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.True(t, meta.RequiresHTTPService)
+	assert.True(t, meta.ExposesHTTPServices)
 	assert.True(t, meta.PassiveEndpoints)
 }
 
@@ -88,7 +88,7 @@ func TestHttpOnlyJavaSourceRest(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.True(t, meta.RequiresHTTPService)
+	assert.True(t, meta.ExposesHTTPServices)
 	assert.True(t, meta.PassiveEndpoints)
 }
 
@@ -109,7 +109,7 @@ func TestHttpOnlyJavaSourceRest2(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.True(t, meta.RequiresHTTPService)
+	assert.True(t, meta.ExposesHTTPServices)
 	assert.True(t, meta.PassiveEndpoints)
 }
 
@@ -131,7 +131,7 @@ func TestNoHttpGroovySource(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.False(t, meta.RequiresHTTPService)
+	assert.False(t, meta.ExposesHTTPServices)
 	assert.False(t, meta.PassiveEndpoints)
 }
 
@@ -153,7 +153,7 @@ func TestHttpOnlyGroovySource(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.True(t, meta.RequiresHTTPService)
+	assert.True(t, meta.ExposesHTTPServices)
 	assert.True(t, meta.PassiveEndpoints)
 }
 
@@ -175,7 +175,7 @@ func TestHttpXMLSource(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.True(t, meta.RequiresHTTPService)
+	assert.True(t, meta.ExposesHTTPServices)
 	assert.False(t, meta.PassiveEndpoints)
 }
 
@@ -198,7 +198,7 @@ func TestHttpOnlyXMLSource(t *testing.T) {
 
 	meta := Extract(catalog, code)
 
-	assert.True(t, meta.RequiresHTTPService)
+	assert.True(t, meta.ExposesHTTPServices)
 	assert.True(t, meta.PassiveEndpoints)
 }
 
@@ -232,7 +232,7 @@ func TestMultilangHTTPOnlySource(t *testing.T) {
 
 	meta := ExtractAll(catalog, codes)
 
-	assert.True(t, meta.RequiresHTTPService)
+	assert.True(t, meta.ExposesHTTPServices)
 	assert.True(t, meta.PassiveEndpoints)
 }
 
@@ -268,6 +268,6 @@ func TestMultilangHTTPSource(t *testing.T) {
 
 	meta := ExtractAll(catalog, codes)
 
-	assert.True(t, meta.RequiresHTTPService)
+	assert.True(t, meta.ExposesHTTPServices)
 	assert.False(t, meta.PassiveEndpoints)
 }
diff --git a/pkg/metadata/types.go b/pkg/metadata/types.go
index 934da27..66565cf 100644
--- a/pkg/metadata/types.go
+++ b/pkg/metadata/types.go
@@ -19,26 +19,9 @@ package metadata
 
 import (
 	"github.com/apache/camel-k/pkg/util/source"
-	"github.com/scylladb/go-set/strset"
 )
 
 // IntegrationMetadata contains aggregate metadata about all Camel routes in a integrations
 type IntegrationMetadata struct {
 	source.Metadata
-	// RequiresHTTPService indicates if the integration needs to be invoked through HTTP
-	RequiresHTTPService bool
-	// PassiveEndpoints indicates that the integration contains only passive endpoints that are activated from
-	// external calls, including HTTP (useful to determine if the integration can scale to 0)
-	PassiveEndpoints bool
-}
-
-// NewIntegrationMetadata --
-func NewIntegrationMetadata() IntegrationMetadata {
-	return IntegrationMetadata{
-		Metadata: source.Metadata{
-			FromURIs:     make([]string, 0),
-			ToURIs:       make([]string, 0),
-			Dependencies: strset.New(),
-		},
-	}
 }
diff --git a/pkg/trait/knative_service.go b/pkg/trait/knative_service.go
index 9c9e671..8a46b92 100644
--- a/pkg/trait/knative_service.go
+++ b/pkg/trait/knative_service.go
@@ -158,7 +158,7 @@ func (t *knativeServiceTrait) Configure(e *Environment) (bool, error) {
 			}
 
 			meta := metadata.ExtractAll(e.CamelCatalog, sources)
-			if !meta.RequiresHTTPService || !meta.PassiveEndpoints {
+			if !meta.ExposesHTTPServices || !meta.PassiveEndpoints {
 				single := 1
 				t.MinScale = &single
 			}
@@ -256,7 +256,7 @@ func (t *knativeServiceTrait) SelectControllerStrategy(e *Environment) (*Control
 	}
 
 	meta := metadata.ExtractAll(e.CamelCatalog, sources)
-	if meta.RequiresHTTPService {
+	if meta.ExposesHTTPServices {
 		return &knativeServiceStrategy, nil
 	}
 	return nil, nil
diff --git a/pkg/trait/service.go b/pkg/trait/service.go
index 6257e9e..882cd48 100644
--- a/pkg/trait/service.go
+++ b/pkg/trait/service.go
@@ -88,7 +88,7 @@ func (t *serviceTrait) Configure(e *Environment) (bool, error) {
 		}
 
 		meta := metadata.ExtractAll(e.CamelCatalog, sources)
-		if !meta.RequiresHTTPService {
+		if !meta.ExposesHTTPServices {
 			e.Integration.Status.SetCondition(
 				v1.IntegrationConditionServiceAvailable,
 				corev1.ConditionFalse,
diff --git a/pkg/util/source/inspector.go b/pkg/util/source/inspector.go
index 934525c..a8b690a 100644
--- a/pkg/util/source/inspector.go
+++ b/pkg/util/source/inspector.go
@@ -18,6 +18,7 @@ limitations under the License.
 package source
 
 import (
+	"fmt"
 	"regexp"
 	"strings"
 
@@ -26,6 +27,8 @@ import (
 	"github.com/apache/camel-k/pkg/util/camel"
 )
 
+type catalog2deps func(*camel.RuntimeCatalog) []string
+
 var (
 	singleQuotedFrom        = regexp.MustCompile(`from\s*\(\s*'([a-zA-Z0-9-]+:[^']+)'`)
 	doubleQuotedFrom        = regexp.MustCompile(`from\s*\(\s*"([a-zA-Z0-9-]+:[^"]+)"`)
@@ -41,8 +44,8 @@ var (
 	jsonLanguageRegexp      = regexp.MustCompile(`.*\.json\(\).*`)
 	circuitBreakerRegexp    = regexp.MustCompile(`.*\.circuitBreaker\(\).*`)
 	restConfigurationRegexp = regexp.MustCompile(`.*restConfiguration\(\).*`)
-	restRegexp              = regexp.MustCompile(`.*rest\(("[a-zA-Z0-9-/]+")*\).*`)
-	restXMLRegexp           = regexp.MustCompile(`^\s*rest\s*{.*`)
+	restRegexp              = regexp.MustCompile(`.*rest\s*\([^)]*\).*`)
+	restClosureRegexp       = regexp.MustCompile(`.*rest\s*{\s*`)
 	groovyLanguageRegexp    = regexp.MustCompile(`.*\.groovy\s*\(.*\).*`)
 	jsonPathLanguageRegexp  = regexp.MustCompile(`.*\.?(jsonpath|jsonpathWriteAsString)\s*\(.*\).*`)
 	ognlRegexp              = regexp.MustCompile(`.*\.ognl\s*\(.*\).*`)
@@ -51,27 +54,91 @@ var (
 	xpathRegexp             = regexp.MustCompile(`.*\.?xpath\s*\(.*\).*`)
 	xtokenizeRegexp         = regexp.MustCompile(`.*\.xtokenize\s*\(.*\).*`)
 
-	sourceDependencies = struct {
-		main    map[*regexp.Regexp]string
-		quarkus map[*regexp.Regexp]string
-	}{
-		main: map[*regexp.Regexp]string{
-			jsonLibraryRegexp:       "camel:jackson",
-			jsonLanguageRegexp:      "camel:jackson",
-			circuitBreakerRegexp:    "camel:hystrix",
-			restConfigurationRegexp: "camel:rest",
-			restRegexp:              "camel:rest",
-			restXMLRegexp:           "camel:rest",
-			groovyLanguageRegexp:    "camel:groovy",
-			jsonPathLanguageRegexp:  "camel:jsonpath",
-			ognlRegexp:              "camel:ognl",
-			mvelRegexp:              "camel:mvel",
-			xqueryRegexp:            "camel:saxon",
-			xpathRegexp:             "camel:xpath",
-			xtokenizeRegexp:         "camel:jaxp",
+	sourceDependencies = map[*regexp.Regexp]catalog2deps{
+		jsonLibraryRegexp: func(_ *camel.RuntimeCatalog) []string {
+			return []string{"camel:jackson"}
+		},
+		jsonLanguageRegexp: func(_ *camel.RuntimeCatalog) []string {
+			return []string{"camel:jackson"}
+		},
+		circuitBreakerRegexp: func(_ *camel.RuntimeCatalog) []string {
+			return []string{"camel:hystrix"}
+		},
+		restConfigurationRegexp: func(catalog *camel.RuntimeCatalog) []string {
+			deps := make([]string, 0)
+			if c, ok := catalog.CamelCatalogSpec.Runtime.Capabilities["rest"]; ok {
+				for _, d := range c.Dependencies {
+					deps = append(deps, fmt.Sprintf("mvn:%s/%s", d.GroupID, d.ArtifactID))
+				}
+			}
+			return deps
+		},
+		restRegexp: func(catalog *camel.RuntimeCatalog) []string {
+			deps := make([]string, 0)
+			if c, ok := catalog.CamelCatalogSpec.Runtime.Capabilities["rest"]; ok {
+				for _, d := range c.Dependencies {
+					deps = append(deps, fmt.Sprintf("mvn:%s/%s", d.GroupID, d.ArtifactID))
+				}
+			}
+			return deps
+		},
+		restClosureRegexp: func(catalog *camel.RuntimeCatalog) []string {
+			deps := make([]string, 0)
+			if c, ok := catalog.CamelCatalogSpec.Runtime.Capabilities["rest"]; ok {
+				for _, d := range c.Dependencies {
+					deps = append(deps, fmt.Sprintf("mvn:%s/%s", d.GroupID, d.ArtifactID))
+				}
+			}
+			return deps
+		},
+		groovyLanguageRegexp: func(catalog *camel.RuntimeCatalog) []string {
+			if dependency, ok := catalog.GetLanguageDependency("groovy"); ok {
+				return []string{dependency}
+			}
+
+			return []string{}
+		},
+		jsonPathLanguageRegexp: func(catalog *camel.RuntimeCatalog) []string {
+			if dependency, ok := catalog.GetLanguageDependency("jsonpath"); ok {
+				return []string{dependency}
+			}
+
+			return []string{}
+		},
+		ognlRegexp: func(catalog *camel.RuntimeCatalog) []string {
+			if dependency, ok := catalog.GetLanguageDependency("ognl"); ok {
+				return []string{dependency}
+			}
+
+			return []string{}
+		},
+		mvelRegexp: func(catalog *camel.RuntimeCatalog) []string {
+			if dependency, ok := catalog.GetLanguageDependency("mvel"); ok {
+				return []string{dependency}
+			}
+
+			return []string{}
+		},
+		xqueryRegexp: func(catalog *camel.RuntimeCatalog) []string {
+			if dependency, ok := catalog.GetLanguageDependency("xquery"); ok {
+				return []string{dependency}
+			}
+
+			return []string{}
+		},
+		xpathRegexp: func(catalog *camel.RuntimeCatalog) []string {
+			if dependency, ok := catalog.GetLanguageDependency("xpath"); ok {
+				return []string{dependency}
+			}
+
+			return []string{}
 		},
-		quarkus: map[*regexp.Regexp]string{
-			xtokenizeRegexp: "camel-quarkus:core-xml",
+		xtokenizeRegexp: func(catalog *camel.RuntimeCatalog) []string {
+			if dependency, ok := catalog.GetLanguageDependency("xtokenize"); ok {
+				return []string{dependency}
+			}
+
+			return []string{}
 		},
 	}
 )
@@ -143,14 +210,12 @@ func (i *baseInspector) discoverDependencies(source v1.SourceSpec, meta *Metadat
 		}
 	}
 
-	for pattern, dep := range sourceDependencies.main {
-		if i.catalog.Runtime.Provider == v1.RuntimeProviderQuarkus {
-			// Check whether quarkus has its own artifact that differs from the standard one
-			if _, ok := sourceDependencies.quarkus[pattern]; ok {
-				dep = sourceDependencies.quarkus[pattern]
-			}
+	for pattern, supplier := range sourceDependencies {
+		if !pattern.MatchString(source.Content) {
+			continue
 		}
-		if pattern.MatchString(source.Content) {
+
+		for _, dep := range supplier(i.catalog) {
 			i.addDependency(dep, meta)
 		}
 	}
@@ -192,3 +257,53 @@ func (i *baseInspector) decodeComponent(uri string) string {
 	}
 	return ""
 }
+
+// hasOnlyPassiveEndpoints returns true if the source has no endpoint that needs to remain always active
+func (i *baseInspector) hasOnlyPassiveEndpoints(fromURIs []string) bool {
+	passivePlusHTTP := make(map[string]bool)
+	i.catalog.VisitSchemes(func(id string, scheme v1.CamelScheme) bool {
+		if scheme.HTTP || scheme.Passive {
+			passivePlusHTTP[id] = true
+		}
+
+		return true
+	})
+
+	return i.containsOnlyURIsIn(fromURIs, passivePlusHTTP)
+}
+
+func (i *baseInspector) containsOnlyURIsIn(fromURI []string, allowed map[string]bool) bool {
+	for _, uri := range fromURI {
+		prefix := i.getURIPrefix(uri)
+		if enabled, ok := allowed[prefix]; !ok || !enabled {
+			return false
+		}
+	}
+	return true
+}
+
+func (i *baseInspector) getURIPrefix(uri string) string {
+	parts := strings.SplitN(uri, ":", 2)
+	if len(parts) > 0 {
+		return parts[0]
+	}
+	return ""
+}
+
+func (i *baseInspector) containsHTTPURIs(fromURI []string) bool {
+	for _, uri := range fromURI {
+		prefix := i.getURIPrefix(uri)
+		scheme, ok := i.catalog.GetScheme(prefix)
+
+		if !ok {
+			// scheme does not exists
+			continue
+		}
+
+		if scheme.HTTP {
+			return true
+		}
+	}
+
+	return false
+}
diff --git a/pkg/util/source/inspector_groovy.go b/pkg/util/source/inspector_groovy.go
index 8ec8823..a37bfc0 100644
--- a/pkg/util/source/inspector_groovy.go
+++ b/pkg/util/source/inspector_groovy.go
@@ -49,5 +49,10 @@ func (i GroovyInspector) Extract(source v1.SourceSpec, meta *Metadata) error {
 
 	i.discoverDependencies(source, meta)
 
+	hasRest := restRegexp.MatchString(source.Content) || restClosureRegexp.MatchString(source.Content)
+
+	meta.ExposesHTTPServices = hasRest || i.containsHTTPURIs(meta.FromURIs)
+	meta.PassiveEndpoints = i.hasOnlyPassiveEndpoints(meta.FromURIs)
+
 	return nil
 }
diff --git a/pkg/util/source/inspector_java_script.go b/pkg/util/source/inspector_java_script.go
index 60e68f3..f79dd3a 100644
--- a/pkg/util/source/inspector_java_script.go
+++ b/pkg/util/source/inspector_java_script.go
@@ -49,5 +49,8 @@ func (i JavaScriptInspector) Extract(source v1.SourceSpec, meta *Metadata) error
 
 	i.discoverDependencies(source, meta)
 
+	meta.ExposesHTTPServices = restRegexp.MatchString(source.Content) || i.containsHTTPURIs(meta.FromURIs)
+	meta.PassiveEndpoints = i.hasOnlyPassiveEndpoints(meta.FromURIs)
+
 	return nil
 }
diff --git a/pkg/util/source/inspector_java_source.go b/pkg/util/source/inspector_java_source.go
index 7b79198..32bd0b0 100644
--- a/pkg/util/source/inspector_java_source.go
+++ b/pkg/util/source/inspector_java_source.go
@@ -45,5 +45,8 @@ func (i JavaSourceInspector) Extract(source v1.SourceSpec, meta *Metadata) error
 
 	i.discoverDependencies(source, meta)
 
+	meta.ExposesHTTPServices = restRegexp.MatchString(source.Content) || i.containsHTTPURIs(meta.FromURIs)
+	meta.PassiveEndpoints = i.hasOnlyPassiveEndpoints(meta.FromURIs)
+
 	return nil
 }
diff --git a/pkg/util/source/inspector_kotlin.go b/pkg/util/source/inspector_kotlin.go
index 44efd09..b949318 100644
--- a/pkg/util/source/inspector_kotlin.go
+++ b/pkg/util/source/inspector_kotlin.go
@@ -45,5 +45,10 @@ func (i KotlinInspector) Extract(source v1.SourceSpec, meta *Metadata) error {
 
 	i.discoverDependencies(source, meta)
 
+	hasRest := restRegexp.MatchString(source.Content) || restClosureRegexp.MatchString(source.Content)
+
+	meta.ExposesHTTPServices = hasRest || i.containsHTTPURIs(meta.FromURIs)
+	meta.PassiveEndpoints = i.hasOnlyPassiveEndpoints(meta.FromURIs)
+
 	return nil
 }
diff --git a/pkg/util/source/inspector_xml.go b/pkg/util/source/inspector_xml.go
index 5ec7b99..48777de 100644
--- a/pkg/util/source/inspector_xml.go
+++ b/pkg/util/source/inspector_xml.go
@@ -45,6 +45,7 @@ func (i XMLInspector) Extract(source v1.SourceSpec, meta *Metadata) error {
 			switch se.Name.Local {
 			case "rest", "restConfiguration":
 				i.addDependency("camel:rest", meta)
+				meta.ExposesHTTPServices = true
 			case "circuitBreaker":
 				i.addDependency("camel:hystrix", meta)
 			case "language":
@@ -77,5 +78,8 @@ func (i XMLInspector) Extract(source v1.SourceSpec, meta *Metadata) error {
 
 	i.discoverDependencies(source, meta)
 
+	meta.ExposesHTTPServices = meta.ExposesHTTPServices || i.containsHTTPURIs(meta.FromURIs)
+	meta.PassiveEndpoints = i.hasOnlyPassiveEndpoints(meta.FromURIs)
+
 	return nil
 }
diff --git a/pkg/util/source/inspector_yaml.go b/pkg/util/source/inspector_yaml.go
index 06a1ce3..e42eb38 100644
--- a/pkg/util/source/inspector_yaml.go
+++ b/pkg/util/source/inspector_yaml.go
@@ -49,6 +49,9 @@ func (inspector YAMLInspector) Extract(source v1.SourceSpec, meta *Metadata) err
 
 	inspector.discoverDependencies(source, meta)
 
+	meta.ExposesHTTPServices = meta.ExposesHTTPServices || inspector.containsHTTPURIs(meta.FromURIs)
+	meta.PassiveEndpoints = inspector.hasOnlyPassiveEndpoints(meta.FromURIs)
+
 	return nil
 }
 
@@ -56,6 +59,7 @@ func (inspector YAMLInspector) parseStep(key string, content interface{}, meta *
 	switch key {
 	case "rest":
 		inspector.addDependency("camel:rest", meta)
+		meta.ExposesHTTPServices = true
 	case "circuitBreaker":
 		inspector.addDependency("camel:hystrix", meta)
 	}
@@ -126,6 +130,5 @@ func (inspector YAMLInspector) parseStep(key string, content interface{}, meta *
 			meta.ToURIs = append(meta.ToURIs, maybeURI)
 		}
 	}
-
 	return nil
 }
diff --git a/pkg/util/source/types.go b/pkg/util/source/types.go
index 09f727a..1802917 100644
--- a/pkg/util/source/types.go
+++ b/pkg/util/source/types.go
@@ -27,4 +27,20 @@ type Metadata struct {
 	ToURIs []string
 	// All inferred dependencies required to run the integration
 	Dependencies *strset.Set
+	// ExposesHTTPServices indicates if a route defined by the source is exposed
+	// through HTTP
+	ExposesHTTPServices bool
+	// PassiveEndpoints indicates that the source contains only passive endpoints that
+	// are activated from external calls, including HTTP (useful to determine if the
+	// integration can scale to 0)
+	PassiveEndpoints bool
+}
+
+// NewMetadata --
+func NewMetadata() Metadata {
+	return Metadata{
+		FromURIs:     make([]string, 0),
+		ToURIs:       make([]string, 0),
+		Dependencies: strset.New(),
+	}
 }