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 2018/12/21 11:05:57 UTC

[camel-k] 04/04: inspect xml source code using streaming parser

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 11ca9c6b20ea200a5179db649190b0c7ae930382
Author: lburgazzoli <lb...@gmail.com>
AuthorDate: Thu Dec 20 23:02:31 2018 +0100

    inspect xml source code using streaming parser
---
 pkg/metadata/metadata.go                 |   5 +-
 pkg/metadata/uris.go                     | 239 -------------------------------
 pkg/util/source/inspector.go             |  89 ++++++++++++
 pkg/util/source/inspector_groovy.go      |  50 +++++++
 pkg/util/source/inspector_java_script.go |  50 +++++++
 pkg/util/source/inspector_java_source.go |  46 ++++++
 pkg/util/source/inspector_kotlin.go      |  46 ++++++
 pkg/util/source/inspector_xml.go         |  89 ++++++++++++
 pkg/util/source/inspector_yaml_flow.go   |  67 +++++++++
 9 files changed, 440 insertions(+), 241 deletions(-)

diff --git a/pkg/metadata/metadata.go b/pkg/metadata/metadata.go
index a696f99..4f7d980 100644
--- a/pkg/metadata/metadata.go
+++ b/pkg/metadata/metadata.go
@@ -21,6 +21,7 @@ import (
 	"sort"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	src "github.com/apache/camel-k/pkg/util/source"
 )
 
 // ExtractAll returns metadata information from all listed source codes
@@ -71,9 +72,9 @@ func merge(m1 IntegrationMetadata, m2 IntegrationMetadata) IntegrationMetadata {
 func Extract(source v1alpha1.SourceSpec) IntegrationMetadata {
 	language := discoverLanguage(source)
 	// TODO: handle error
-	fromURIs, _ := GetInspectorForLanguage(language).FromURIs(source)
+	fromURIs, _ := src.InspectorForLanguage(language).FromURIs(source)
 	// TODO:: handle error
-	toURIs, _ := GetInspectorForLanguage(language).ToURIs(source)
+	toURIs, _ := src.InspectorForLanguage(language).ToURIs(source)
 	dependencies := discoverDependencies(source, fromURIs, toURIs)
 	requiresHTTPService := requiresHTTPService(source, fromURIs)
 	passiveEndpoints := hasOnlyPassiveEndpoints(source, fromURIs)
diff --git a/pkg/metadata/uris.go b/pkg/metadata/uris.go
deleted file mode 100644
index c267cfa..0000000
--- a/pkg/metadata/uris.go
+++ /dev/null
@@ -1,239 +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"
-
-	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
-	yaml "gopkg.in/yaml.v2"
-)
-
-var (
-	singleQuotedFrom = regexp.MustCompile(`from\s*\(\s*'([a-z0-9-]+:[^']+)'\s*\)`)
-	doubleQuotedFrom = regexp.MustCompile(`from\s*\(\s*"([a-z0-9-]+:[^"]+)"\s*\)`)
-	singleQuotedTo   = regexp.MustCompile(`\.to\s*\(\s*'([a-z0-9-]+:[^']+)'\s*\)`)
-	singleQuotedToD  = regexp.MustCompile(`\.toD\s*\(\s*'([a-z0-9-]+:[^']+)'\s*\)`)
-	singleQuotedToF  = regexp.MustCompile(`\.toF\s*\(\s*'([a-z0-9-]+:[^']+)'[^)]*\)`)
-	doubleQuotedTo   = regexp.MustCompile(`\.to\s*\(\s*"([a-z0-9-]+:[^"]+)"\s*\)`)
-	doubleQuotedToD  = regexp.MustCompile(`\.toD\s*\(\s*"([a-z0-9-]+:[^"]+)"\s*\)`)
-	doubleQuotedToF  = regexp.MustCompile(`\.toF\s*\(\s*"([a-z0-9-]+:[^"]+)"[^)]*\)`)
-	xmlTagFrom       = regexp.MustCompile(`<\s*from\s+[^>]*uri\s*=\s*"([a-z0-9-]+:[^"]+)"[^>]*>`)
-	xmlTagTo         = regexp.MustCompile(`<\s*to\s+[^>]*uri\s*=\s*"([a-z0-9-]+:[^"]+)"[^>]*>`)
-	xmlTagToD        = regexp.MustCompile(`<\s*toD\s+[^>]*uri\s*=\s*"([a-z0-9-]+:[^"]+)"[^>]*>`)
-)
-
-// LanguageInspector --
-type LanguageInspector interface {
-	FromURIs(v1alpha1.SourceSpec) ([]string, error)
-	ToURIs(v1alpha1.SourceSpec) ([]string, error)
-}
-
-type languageInspector struct {
-	from func(v1alpha1.SourceSpec) ([]string, error)
-	to   func(v1alpha1.SourceSpec) ([]string, error)
-}
-
-func (i languageInspector) FromURIs(source v1alpha1.SourceSpec) ([]string, error) {
-	return i.from(source)
-}
-func (i languageInspector) ToURIs(source v1alpha1.SourceSpec) ([]string, error) {
-	return i.to(source)
-}
-
-// GetInspectorForLanguage --
-func GetInspectorForLanguage(language v1alpha1.Language) LanguageInspector {
-	switch language {
-	case v1alpha1.LanguageJavaSource:
-		return &languageInspector{
-			from: func(source v1alpha1.SourceSpec) ([]string, error) {
-				answer := findAllDistinctStringSubmatch(
-					source.Content,
-					doubleQuotedFrom,
-				)
-
-				return answer, nil
-			},
-			to: func(source v1alpha1.SourceSpec) ([]string, error) {
-				answer := findAllDistinctStringSubmatch(
-					source.Content,
-					doubleQuotedTo,
-					doubleQuotedToD,
-					doubleQuotedToF,
-				)
-
-				return answer, nil
-			},
-		}
-	case v1alpha1.LanguageXML:
-		return &languageInspector{
-			from: func(source v1alpha1.SourceSpec) ([]string, error) {
-				answer := findAllDistinctStringSubmatch(
-					source.Content,
-					xmlTagFrom,
-				)
-
-				return answer, nil
-			},
-			to: func(source v1alpha1.SourceSpec) ([]string, error) {
-				answer := findAllDistinctStringSubmatch(
-					source.Content,
-					xmlTagTo,
-					xmlTagToD,
-				)
-
-				return answer, nil
-			},
-		}
-	case v1alpha1.LanguageGroovy:
-		return &languageInspector{
-			from: func(source v1alpha1.SourceSpec) ([]string, error) {
-				answer := findAllDistinctStringSubmatch(
-					source.Content,
-					singleQuotedFrom,
-					doubleQuotedFrom,
-				)
-
-				return answer, nil
-			},
-			to: func(source v1alpha1.SourceSpec) ([]string, error) {
-				answer := findAllDistinctStringSubmatch(
-					source.Content,
-					singleQuotedTo,
-					doubleQuotedTo,
-					singleQuotedToD,
-					doubleQuotedToD,
-					singleQuotedToF,
-					doubleQuotedToF,
-				)
-
-				return answer, nil
-			},
-		}
-	case v1alpha1.LanguageJavaScript:
-		return &languageInspector{
-			from: func(source v1alpha1.SourceSpec) ([]string, error) {
-				answer := findAllDistinctStringSubmatch(
-					source.Content,
-					singleQuotedFrom,
-					doubleQuotedFrom,
-				)
-
-				return answer, nil
-			},
-			to: func(source v1alpha1.SourceSpec) ([]string, error) {
-				answer := findAllDistinctStringSubmatch(
-					source.Content,
-					singleQuotedTo,
-					doubleQuotedTo,
-					singleQuotedToD,
-					doubleQuotedToD,
-					singleQuotedToF,
-					doubleQuotedToF,
-				)
-
-				return answer, nil
-			},
-		}
-	case v1alpha1.LanguageKotlin:
-		return &languageInspector{
-			from: func(source v1alpha1.SourceSpec) ([]string, error) {
-				answer := findAllDistinctStringSubmatch(
-					source.Content,
-					doubleQuotedFrom,
-				)
-
-				return answer, nil
-			},
-			to: func(source v1alpha1.SourceSpec) ([]string, error) {
-				answer := findAllDistinctStringSubmatch(
-					source.Content,
-					doubleQuotedTo,
-					doubleQuotedToD,
-					doubleQuotedToF,
-				)
-
-				return answer, nil
-			},
-		}
-	case v1alpha1.LanguageYamlFlow:
-		var flows []v1alpha1.Flow
-
-		return &languageInspector{
-			from: func(source v1alpha1.SourceSpec) ([]string, error) {
-				if err := yaml.Unmarshal([]byte(source.Content), &flows); err != nil {
-					return []string{}, nil
-				}
-
-				uris := make([]string, 0)
-
-				for _, flow := range flows {
-					if flow.Steps[0].URI != "" {
-						uris = append(uris, flow.Steps[0].URI)
-					}
-
-				}
-				return uris, nil
-			},
-			to: func(source v1alpha1.SourceSpec) ([]string, error) {
-				if err := yaml.Unmarshal([]byte(source.Content), &flows); err != nil {
-					return []string{}, nil
-				}
-
-				uris := make([]string, 0)
-
-				for _, flow := range flows {
-					for i := 1; i < len(flow.Steps); i++ {
-						if flow.Steps[i].URI != "" {
-							uris = append(uris, flow.Steps[i].URI)
-						}
-					}
-				}
-
-				return uris, nil
-			},
-		}
-	}
-	return &languageInspector{
-		from: func(source v1alpha1.SourceSpec) ([]string, error) {
-			return []string{}, nil
-		},
-		to: func(source v1alpha1.SourceSpec) ([]string, error) {
-			return []string{}, nil
-		},
-	}
-}
-
-func findAllDistinctStringSubmatch(data string, regexps ...*regexp.Regexp) []string {
-	candidates := make([]string, 0)
-	alreadyFound := make(map[string]bool)
-	for _, reg := range regexps {
-		hits := reg.FindAllStringSubmatch(data, -1)
-		for _, hit := range hits {
-			if len(hit) > 1 {
-				for _, match := range hit[1:] {
-					if _, ok := alreadyFound[match]; !ok {
-						alreadyFound[match] = true
-						candidates = append(candidates, match)
-					}
-				}
-			}
-		}
-	}
-	return candidates
-}
diff --git a/pkg/util/source/inspector.go b/pkg/util/source/inspector.go
new file mode 100644
index 0000000..db76c49
--- /dev/null
+++ b/pkg/util/source/inspector.go
@@ -0,0 +1,89 @@
+/*
+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 source
+
+import (
+	"regexp"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+)
+
+var (
+	singleQuotedFrom = regexp.MustCompile(`from\s*\(\s*'([a-z0-9-]+:[^']+)'\s*\)`)
+	doubleQuotedFrom = regexp.MustCompile(`from\s*\(\s*"([a-z0-9-]+:[^"]+)"\s*\)`)
+	singleQuotedTo   = regexp.MustCompile(`\.to\s*\(\s*'([a-z0-9-]+:[^']+)'\s*\)`)
+	singleQuotedToD  = regexp.MustCompile(`\.toD\s*\(\s*'([a-z0-9-]+:[^']+)'\s*\)`)
+	singleQuotedToF  = regexp.MustCompile(`\.toF\s*\(\s*'([a-z0-9-]+:[^']+)'[^)]*\)`)
+	doubleQuotedTo   = regexp.MustCompile(`\.to\s*\(\s*"([a-z0-9-]+:[^"]+)"\s*\)`)
+	doubleQuotedToD  = regexp.MustCompile(`\.toD\s*\(\s*"([a-z0-9-]+:[^"]+)"\s*\)`)
+	doubleQuotedToF  = regexp.MustCompile(`\.toF\s*\(\s*"([a-z0-9-]+:[^"]+)"[^)]*\)`)
+)
+
+// Inspector --
+type Inspector interface {
+	FromURIs(v1alpha1.SourceSpec) ([]string, error)
+	ToURIs(v1alpha1.SourceSpec) ([]string, error)
+}
+
+// InspectorForLanguage --
+func InspectorForLanguage(language v1alpha1.Language) Inspector {
+	switch language {
+	case v1alpha1.LanguageJavaSource:
+		return &JavaSourceInspector{}
+	case v1alpha1.LanguageXML:
+		return &XMLInspector{}
+	case v1alpha1.LanguageGroovy:
+		return &GroovyInspector{}
+	case v1alpha1.LanguageJavaScript:
+		return &JavaScriptInspector{}
+	case v1alpha1.LanguageKotlin:
+		return &KotlinInspector{}
+	case v1alpha1.LanguageYamlFlow:
+		return &YAMLFlowInspector{}
+	}
+	return &noInspector{}
+}
+
+func findAllDistinctStringSubmatch(data string, regexps ...*regexp.Regexp) []string {
+	candidates := make([]string, 0)
+	alreadyFound := make(map[string]bool)
+	for _, reg := range regexps {
+		hits := reg.FindAllStringSubmatch(data, -1)
+		for _, hit := range hits {
+			if len(hit) > 1 {
+				for _, match := range hit[1:] {
+					if _, ok := alreadyFound[match]; !ok {
+						alreadyFound[match] = true
+						candidates = append(candidates, match)
+					}
+				}
+			}
+		}
+	}
+	return candidates
+}
+
+type noInspector struct {
+}
+
+func (i noInspector) FromURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	return []string{}, nil
+}
+func (i noInspector) ToURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	return []string{}, nil
+}
diff --git a/pkg/util/source/inspector_groovy.go b/pkg/util/source/inspector_groovy.go
new file mode 100644
index 0000000..ddcd874
--- /dev/null
+++ b/pkg/util/source/inspector_groovy.go
@@ -0,0 +1,50 @@
+/*
+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 source
+
+import "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+
+// GroovyInspector --
+type GroovyInspector struct {
+}
+
+// FromURIs --
+func (i GroovyInspector) FromURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	answer := findAllDistinctStringSubmatch(
+		source.Content,
+		singleQuotedFrom,
+		doubleQuotedFrom,
+	)
+
+	return answer, nil
+}
+
+// ToURIs --
+func (i GroovyInspector) ToURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	answer := findAllDistinctStringSubmatch(
+		source.Content,
+		singleQuotedTo,
+		doubleQuotedTo,
+		singleQuotedToD,
+		doubleQuotedToD,
+		singleQuotedToF,
+		doubleQuotedToF,
+	)
+
+	return answer, nil
+}
diff --git a/pkg/util/source/inspector_java_script.go b/pkg/util/source/inspector_java_script.go
new file mode 100644
index 0000000..913fc8d
--- /dev/null
+++ b/pkg/util/source/inspector_java_script.go
@@ -0,0 +1,50 @@
+/*
+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 source
+
+import "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+
+// JavaScriptInspector --
+type JavaScriptInspector struct {
+}
+
+// FromURIs --
+func (i JavaScriptInspector) FromURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	answer := findAllDistinctStringSubmatch(
+		source.Content,
+		singleQuotedFrom,
+		doubleQuotedFrom,
+	)
+
+	return answer, nil
+}
+
+// ToURIs --
+func (i JavaScriptInspector) ToURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	answer := findAllDistinctStringSubmatch(
+		source.Content,
+		singleQuotedTo,
+		doubleQuotedTo,
+		singleQuotedToD,
+		doubleQuotedToD,
+		singleQuotedToF,
+		doubleQuotedToF,
+	)
+
+	return answer, nil
+}
diff --git a/pkg/util/source/inspector_java_source.go b/pkg/util/source/inspector_java_source.go
new file mode 100644
index 0000000..4a22953
--- /dev/null
+++ b/pkg/util/source/inspector_java_source.go
@@ -0,0 +1,46 @@
+/*
+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 source
+
+import "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+
+// JavaSourceInspector --
+type JavaSourceInspector struct {
+}
+
+// FromURIs --
+func (i JavaSourceInspector) FromURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	answer := findAllDistinctStringSubmatch(
+		source.Content,
+		doubleQuotedFrom,
+	)
+
+	return answer, nil
+}
+
+// ToURIs --
+func (i JavaSourceInspector) ToURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	answer := findAllDistinctStringSubmatch(
+		source.Content,
+		doubleQuotedTo,
+		doubleQuotedToD,
+		doubleQuotedToF,
+	)
+
+	return answer, nil
+}
diff --git a/pkg/util/source/inspector_kotlin.go b/pkg/util/source/inspector_kotlin.go
new file mode 100644
index 0000000..111bf14
--- /dev/null
+++ b/pkg/util/source/inspector_kotlin.go
@@ -0,0 +1,46 @@
+/*
+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 source
+
+import "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+
+// KotlinInspector --
+type KotlinInspector struct {
+}
+
+// FromURIs --
+func (i KotlinInspector) FromURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	answer := findAllDistinctStringSubmatch(
+		source.Content,
+		doubleQuotedFrom,
+	)
+
+	return answer, nil
+}
+
+// ToURIs --
+func (i KotlinInspector) ToURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	answer := findAllDistinctStringSubmatch(
+		source.Content,
+		doubleQuotedTo,
+		doubleQuotedToD,
+		doubleQuotedToF,
+	)
+
+	return answer, nil
+}
diff --git a/pkg/util/source/inspector_xml.go b/pkg/util/source/inspector_xml.go
new file mode 100644
index 0000000..c13f1e6
--- /dev/null
+++ b/pkg/util/source/inspector_xml.go
@@ -0,0 +1,89 @@
+/*
+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 source
+
+import (
+	"encoding/xml"
+	"strings"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+)
+
+// XMLInspector --
+type XMLInspector struct {
+}
+
+// FromURIs --
+func (i XMLInspector) FromURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	content := strings.NewReader(source.Content)
+	decoder := xml.NewDecoder(content)
+
+	uris := make([]string, 0)
+
+	for {
+		// Read tokens from the XML document in a stream.
+		t, _ := decoder.Token()
+		if t == nil {
+			break
+		}
+
+		switch se := t.(type) {
+		case xml.StartElement:
+			switch se.Name.Local {
+			case "from", "fromF":
+				for _, a := range se.Attr {
+					if a.Name.Local == "uri" {
+						uris = append(uris, a.Value)
+					}
+				}
+			}
+		}
+	}
+
+	return uris, nil
+}
+
+// ToURIs --
+func (i XMLInspector) ToURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	content := strings.NewReader(source.Content)
+	decoder := xml.NewDecoder(content)
+
+	uris := make([]string, 0)
+
+	for {
+		// Read tokens from the XML document in a stream.
+		t, _ := decoder.Token()
+		if t == nil {
+			break
+		}
+
+		switch se := t.(type) {
+		case xml.StartElement:
+			switch se.Name.Local {
+			case "to", "toD", "toF":
+				for _, a := range se.Attr {
+					if a.Name.Local == "uri" {
+						uris = append(uris, a.Value)
+					}
+				}
+			}
+		}
+	}
+
+	return uris, nil
+}
diff --git a/pkg/util/source/inspector_yaml_flow.go b/pkg/util/source/inspector_yaml_flow.go
new file mode 100644
index 0000000..e677b4d
--- /dev/null
+++ b/pkg/util/source/inspector_yaml_flow.go
@@ -0,0 +1,67 @@
+/*
+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 source
+
+import (
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	yaml "gopkg.in/yaml.v2"
+)
+
+// YAMLFlowInspector --
+type YAMLFlowInspector struct {
+}
+
+// FromURIs --
+func (i YAMLFlowInspector) FromURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	var flows []v1alpha1.Flow
+
+	if err := yaml.Unmarshal([]byte(source.Content), &flows); err != nil {
+		return []string{}, nil
+	}
+
+	uris := make([]string, 0)
+
+	for _, flow := range flows {
+		if flow.Steps[0].URI != "" {
+			uris = append(uris, flow.Steps[0].URI)
+		}
+
+	}
+	return uris, nil
+}
+
+// ToURIs --
+func (i YAMLFlowInspector) ToURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	var flows []v1alpha1.Flow
+
+	if err := yaml.Unmarshal([]byte(source.Content), &flows); err != nil {
+		return []string{}, nil
+	}
+
+	uris := make([]string, 0)
+
+	for _, flow := range flows {
+		for i := 1; i < len(flow.Steps); i++ {
+			if flow.Steps[i].URI != "" {
+				uris = append(uris, flow.Steps[i].URI)
+			}
+		}
+	}
+
+	return uris, nil
+}