You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@camel.apache.org by GitBox <gi...@apache.org> on 2018/09/12 07:09:36 UTC

[GitHub] nicolaferraro closed pull request #47: Route loaders should derive language from 'kamel run --language' #46

nicolaferraro closed pull request #47: Route loaders should derive language from 'kamel run --language' #46
URL: https://github.com/apache/camel-k/pull/47
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index 8b16b1e..2e4d8d2 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -277,6 +277,11 @@ func (in *SourceSpec) DeepCopyInto(out *SourceSpec) {
 		*out = new(string)
 		**out = **in
 	}
+	if in.Language != nil {
+		in, out := &in.Language, &out.Language
+		*out = new(string)
+		**out = **in
+	}
 	return
 }
 
diff --git a/pkg/build/api/types.go b/pkg/build/api/types.go
index b94a9e7..5fc1395 100644
--- a/pkg/build/api/types.go
+++ b/pkg/build/api/types.go
@@ -29,8 +29,9 @@ type BuildIdentifier struct {
 }
 
 type Code struct {
-	Name    string
-	Content string
+	Name     string
+	Content  string
+	Language string
 }
 
 // represents the result of a build
diff --git a/pkg/build/local/local_builder.go b/pkg/build/local/local_builder.go
index 38a9812..f1ed76a 100644
--- a/pkg/build/local/local_builder.go
+++ b/pkg/build/local/local_builder.go
@@ -131,8 +131,9 @@ func (b *localBuilder) execute(source build.BuildSource) (string, error) {
 			source.Code.Name: source.Code.Content,
 		},
 		Env: map[string]string{
-			"JAVA_MAIN_CLASS":    "org.apache.camel.k.jvm.Application",
-			"CAMEL_K_ROUTES_URI": "classpath:" + source.Code.Name,
+			"JAVA_MAIN_CLASS":         "org.apache.camel.k.jvm.Application",
+			"CAMEL_K_ROUTES_URI":      "classpath:" + source.Code.Name,
+			"CAMEL_K_ROUTES_LANGUAGE": source.Code.Language,
 		},
 	}
 
diff --git a/pkg/stub/action/integration/build.go b/pkg/stub/action/integration/build.go
index 25747cc..22f006a 100644
--- a/pkg/stub/action/integration/build.go
+++ b/pkg/stub/action/integration/build.go
@@ -55,8 +55,9 @@ func (b *BuildAction) Handle(integration *v1alpha1.Integration) error {
 		b.buildManager.Start(api.BuildSource{
 			Identifier: buildIdentifier,
 			Code: api.Code{
-				Name:    *integration.Spec.Source.Name,
-				Content: *integration.Spec.Source.Content,
+				Name:     *integration.Spec.Source.Name,
+				Content:  *integration.Spec.Source.Content,
+				Language: *integration.Spec.Source.Language,
 			}, // FIXME possible panic
 		})
 		logrus.Info("Build started")
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java
index dbca9f1..bec284f 100644
--- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java
@@ -18,23 +18,19 @@
 
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.main.Main;
+import org.apache.camel.util.ObjectHelper;
 
 public class Application {
-    public static final String ENV_CAMEL_K_ROUTES_URI = "CAMEL_K_ROUTES_URI";
-    public static final String SCHEME_CLASSPATH = "classpath:";
-    public static final String SCHEME_FILE = "file:";
 
     public static void main(String[] args) throws Exception {
-        final String resource = System.getenv(ENV_CAMEL_K_ROUTES_URI);
+        final String resource = System.getenv(Routes.ENV_CAMEL_K_ROUTES_URI);
+        final String language = System.getenv(Routes.ENV_CAMEL_K_ROUTES_LANGUAGE);
 
-        if (resource == null || resource.trim().length() == 0) {
-            throw new IllegalStateException("No valid resource found in " + ENV_CAMEL_K_ROUTES_URI + " environment variable");
-        }
-        if (!resource.startsWith(SCHEME_CLASSPATH) && !resource.startsWith(SCHEME_FILE)) {
-            throw new IllegalStateException("No valid resource format, expected scheme:path, found " + resource);
+        if (ObjectHelper.isEmpty(resource)) {
+            throw new IllegalStateException("No valid resource found in " + Routes.ENV_CAMEL_K_ROUTES_URI + " environment variable");
         }
 
-        RoutesLoader loader = RouteLoaders.loaderFor(resource);
+        RoutesLoader loader = Routes.loaderFor(resource, language);
         RouteBuilder routes = loader.load(resource);
 
         if (routes == null) {
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Routes.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Routes.java
new file mode 100644
index 0000000..b2c87d4
--- /dev/null
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Routes.java
@@ -0,0 +1,88 @@
+/**
+ * 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 org.apache.camel.k.jvm;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import org.apache.camel.util.ObjectHelper;
+import org.apache.commons.lang3.StringUtils;
+
+public final class Routes {
+    public static final String ENV_CAMEL_K_ROUTES_URI = "CAMEL_K_ROUTES_URI";
+    public static final String ENV_CAMEL_K_ROUTES_LANGUAGE = "CAMEL_K_ROUTES_LANGUAGE";
+    public static final String SCHEME_CLASSPATH = "classpath:";
+    public static final String SCHEME_FILE = "file:";
+
+    private Routes() {
+    }
+
+    public static boolean isScripting(String resource) {
+        return resource.endsWith(".java") || resource.endsWith(".js") || resource.endsWith(".groovy");
+    }
+
+    public static RoutesLoader loaderForLanguage(String language) {
+        for (RoutesLoader loader: RoutesLoaders.values()) {
+            if (loader.getSupportedLanguages().contains(language)) {
+                return loader;
+            }
+        }
+
+        throw new IllegalArgumentException("Unable to find loader for language: " + language);
+    }
+
+    public static RoutesLoader loaderForResource(String resource) {
+        if (!resource.startsWith(SCHEME_CLASSPATH) && !resource.startsWith(SCHEME_FILE)) {
+            throw new IllegalArgumentException("No valid resource format, expected scheme:path, found " + resource);
+        }
+
+        for (RoutesLoader loader: RoutesLoaders.values()) {
+            if (loader.test(resource)) {
+                return loader;
+            }
+        }
+
+        throw new IllegalArgumentException("Unable to find loader for: " + resource);
+    }
+
+    public static RoutesLoader loaderFor(String resource, String language) {
+        if (!resource.startsWith(SCHEME_CLASSPATH) && !resource.startsWith(SCHEME_FILE)) {
+            throw new IllegalArgumentException("No valid resource format, expected scheme:path, found " + resource);
+        }
+
+        return ObjectHelper.isEmpty(language)
+            ? loaderForResource(resource)
+            : loaderForLanguage(language);
+    }
+
+    static InputStream loadResourceAsInputStream(String resource) throws IOException {
+        if (resource.startsWith(SCHEME_CLASSPATH)) {
+            String location = StringUtils.removeStart(resource, SCHEME_CLASSPATH);
+            if (!location.startsWith("/")) {
+                location = "/" + location;
+            }
+
+            return Application.class.getResourceAsStream(location);
+        } else {
+            return Files.newInputStream(
+                Paths.get(resource.substring(SCHEME_FILE.length()))
+            );
+        }
+    }
+}
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoader.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoader.java
index 9589822..1446b55 100644
--- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoader.java
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoader.java
@@ -16,10 +16,25 @@
  */
 package org.apache.camel.k.jvm;
 
+import java.util.List;
 import java.util.function.Predicate;
 
 import org.apache.camel.builder.RouteBuilder;
 
 public interface RoutesLoader extends Predicate<String> {
+    /**
+     * Provides a list of the languages supported by this loader.
+     *
+     * @return the supported languages.
+     */
+    List<String> getSupportedLanguages();
+
+    /**
+     * Creates a camel {@link RouteBuilder} from the given resource.
+     *
+     * @param resource the location fo the resource to load.
+     * @return the RouteBuilder.
+     * @throws Exception
+     */
     RouteBuilder load(String resource) throws Exception;
 }
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RouteLoaders.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoaders.java
similarity index 74%
rename from runtime/jvm/src/main/java/org/apache/camel/k/jvm/RouteLoaders.java
rename to runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoaders.java
index 48a3fb6..ab1bc5c 100644
--- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RouteLoaders.java
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoaders.java
@@ -16,12 +16,11 @@
  */
 package org.apache.camel.k.jvm;
 
-import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
-import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
 import java.util.function.Function;
 import javax.script.Bindings;
 import javax.script.ScriptEngine;
@@ -40,16 +39,24 @@
 import org.codehaus.groovy.control.CompilerConfiguration;
 import org.joor.Reflect;
 
-public enum RouteLoaders implements RoutesLoader {
+import static org.apache.camel.k.jvm.Routes.SCHEME_CLASSPATH;
+
+public enum RoutesLoaders implements RoutesLoader {
     JavaClass {
+        @Override
+        public List<String> getSupportedLanguages() {
+            return Arrays.asList("class");
+        }
+
         @Override
         public boolean test(String resource) {
-            return !isScripting(resource) && hasSupportedScheme(resource);
+            //TODO: add support for compiled classes
+            return !Routes.isScripting(resource) && !resource.endsWith(".class");
         }
 
         @Override
         public RouteBuilder load(String resource) throws Exception {
-            String path = resource.substring(Application.SCHEME_CLASSPATH.length());
+            String path = resource.substring(SCHEME_CLASSPATH.length());
             Class<?> type = Class.forName(path);
 
             if (!RouteBuilder.class.isAssignableFrom(type)) {
@@ -60,14 +67,22 @@ public RouteBuilder load(String resource) throws Exception {
         }
     },
     JavaSource {
+        @Override
+        public List<String> getSupportedLanguages() {
+            return Arrays.asList("java");
+        }
+
         @Override
         public boolean test(String resource) {
-            return isScripting(resource, "java") && hasSupportedScheme(resource);
+            String ext = StringUtils.substringAfterLast(resource, ".");
+            List<String> langs = getSupportedLanguages();
+
+            return langs.contains(ext);
         }
 
         @Override
         public RouteBuilder load(String resource) throws Exception {
-            try (InputStream is = is(resource)) {
+            try (InputStream is = Routes.loadResourceAsInputStream(resource)) {
                 String name = StringUtils.substringAfter(resource, ":");
                 name = StringUtils.removeEnd(name, ".java");
                 name = StringUtils.removeStart(name, "/");
@@ -77,9 +92,17 @@ public RouteBuilder load(String resource) throws Exception {
         }
     },
     JavaScript {
+        @Override
+        public List<String> getSupportedLanguages() {
+            return Arrays.asList("js");
+        }
+
         @Override
         public boolean test(String resource) {
-            return isScripting(resource, "js") && hasSupportedScheme(resource);
+            String ext = StringUtils.substringAfterLast(resource, ".");
+            List<String> langs = getSupportedLanguages();
+
+            return langs.contains(ext);
         }
 
         @Override
@@ -98,7 +121,7 @@ public void configure() throws Exception {
                     bindings.put("components", new Components(context));
                     bindings.put("from", (Function<String, RouteDefinition>) uri -> from(uri));
 
-                    try (InputStream is = is(resource)) {
+                    try (InputStream is = Routes.loadResourceAsInputStream(resource)) {
                         engine.eval(new InputStreamReader(is), bindings);
                     }
                 }
@@ -106,9 +129,17 @@ public void configure() throws Exception {
         }
     },
     Groovy {
+        @Override
+        public List<String> getSupportedLanguages() {
+            return Arrays.asList("groovy");
+        }
+
         @Override
         public boolean test(String resource) {
-            return isScripting(resource, "groovy") && hasSupportedScheme(resource);
+            String ext = StringUtils.substringAfterLast(resource, ".");
+            List<String> langs = getSupportedLanguages();
+
+            return langs.contains(ext);
         }
 
         @Override
@@ -122,7 +153,7 @@ public void configure() throws Exception {
                     ClassLoader cl = Thread.currentThread().getContextClassLoader();
                     GroovyShell sh = new GroovyShell(cl, new Binding(), cc);
 
-                    try (InputStream is = is(resource)) {
+                    try (InputStream is = Routes.loadResourceAsInputStream(resource)) {
                         Reader reader = new InputStreamReader(is);
                         DelegatingScript script = (DelegatingScript) sh.parse(reader);
 
@@ -142,42 +173,6 @@ public void configure() throws Exception {
     // TODO: move to a dedicate class
     // ********************************
 
-    public static boolean isScripting(String resource, String type) {
-        return type.startsWith(".") ? resource.endsWith(type) : resource.endsWith("." + type);
-    }
-
-    public static boolean isScripting(String resource) {
-        return resource.endsWith(".java") || resource.endsWith(".js") || resource.endsWith(".groovy");
-    }
-
-    public static boolean hasSupportedScheme(String resource) {
-        return resource.startsWith(Application.SCHEME_CLASSPATH) || resource.startsWith(Application.SCHEME_FILE);
-    }
-
-    public static RoutesLoader loaderFor(String resource) {
-        for (RoutesLoader loader: RouteLoaders.values()) {
-            if (loader.test(resource)) {
-                return loader;
-            }
-        }
-
-        throw new IllegalArgumentException("Unable to find loader for: " + resource);
-    }
-
-    private static InputStream is(String resource) throws IOException {
-        if (resource.startsWith(Application.SCHEME_CLASSPATH)) {
-            String location = StringUtils.removeStart(resource, Application.SCHEME_CLASSPATH);
-            if (!location.startsWith("/")) {
-                location = "/" + location;
-            }
-
-            return Application.class.getResourceAsStream(location);
-        } else {
-            return Files.newInputStream(
-                Paths.get(resource.substring(Application.SCHEME_FILE.length()))
-            );
-        }
-    }
 
     public static class Components {
         private CamelContext context;
diff --git a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/ApplicationTest.java b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/ApplicationTest.java
index e43d711..0b576dd 100644
--- a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/ApplicationTest.java
+++ b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/ApplicationTest.java
@@ -1,3 +1,19 @@
+/**
+ * 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 org.apache.camel.k.jvm;
 
 import org.junit.Ignore;
diff --git a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/MyRoutes.java b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/MyRoutes.java
index c92f35a..3869f2d 100644
--- a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/MyRoutes.java
+++ b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/MyRoutes.java
@@ -1,3 +1,19 @@
+/**
+ * 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 org.apache.camel.k.jvm;
 
 import org.apache.camel.builder.RouteBuilder;
diff --git a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/RouteLoadersTest.java b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/RoutesLoadersTest.java
similarity index 70%
rename from runtime/jvm/src/test/java/org/apache/camel/k/jvm/RouteLoadersTest.java
rename to runtime/jvm/src/test/java/org/apache/camel/k/jvm/RoutesLoadersTest.java
index 8701558..e083464 100644
--- a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/RouteLoadersTest.java
+++ b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/RoutesLoadersTest.java
@@ -25,15 +25,15 @@
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-public class RouteLoadersTest {
+public class RoutesLoadersTest {
 
     @Test
     public void testLoadClass() throws Exception {
         String resource = "classpath:" + MyRoutes.class.getCanonicalName();
-        RoutesLoader loader = RouteLoaders.loaderFor(resource);
+        RoutesLoader loader = Routes.loaderForResource(resource);
         RouteBuilder builder = loader.load(resource);
 
-        assertThat(loader).isSameAs(RouteLoaders.JavaClass);
+        assertThat(loader).isSameAs(RoutesLoaders.JavaClass);
         assertThat(builder).isNotNull();
 
         builder.configure();
@@ -47,10 +47,10 @@ public void testLoadClass() throws Exception {
     @Test
     public void testLoadJava() throws Exception {
         String resource = "classpath:MyRoutes.java";
-        RoutesLoader loader = RouteLoaders.loaderFor(resource);
+        RoutesLoader loader = Routes.loaderForResource(resource);
         RouteBuilder builder = loader.load(resource);
 
-        assertThat(loader).isSameAs(RouteLoaders.JavaSource);
+        assertThat(loader).isSameAs(RoutesLoaders.JavaSource);
         assertThat(builder).isNotNull();
 
         builder.configure();
@@ -64,10 +64,27 @@ public void testLoadJava() throws Exception {
     @Test
     public void testLoadJavaScript() throws Exception {
         String resource = "classpath:routes.js";
-        RoutesLoader loader = RouteLoaders.loaderFor(resource);
+        RoutesLoader loader = Routes.loaderForResource(resource);
         RouteBuilder builder = loader.load(resource);
 
-        assertThat(loader).isSameAs(RouteLoaders.JavaScript);
+        assertThat(loader).isSameAs(RoutesLoaders.JavaScript);
+        assertThat(builder).isNotNull();
+
+        builder.configure();
+
+        List<RouteDefinition> routes = builder.getRouteCollection().getRoutes();
+        assertThat(routes).hasSize(1);
+        assertThat(routes.get(0).getInputs().get(0).getEndpointUri()).isEqualTo("timer:tick");
+        assertThat(routes.get(0).getOutputs().get(0)).isInstanceOf(ToDefinition.class);
+    }
+
+    @Test
+    public void testLoadJavaScriptWithCustomExtension() throws Exception {
+        String resource = "classpath:routes.mytype";
+        RoutesLoader loader = Routes.loaderFor(resource, "js");
+        RouteBuilder builder = loader.load(resource);
+
+        assertThat(loader).isSameAs(RoutesLoaders.JavaScript);
         assertThat(builder).isNotNull();
 
         builder.configure();
@@ -81,10 +98,10 @@ public void testLoadJavaScript() throws Exception {
     @Test
     public void testLoadGroovy() throws Exception {
         String resource = "classpath:routes.groovy";
-        RoutesLoader loader = RouteLoaders.loaderFor(resource);
+        RoutesLoader loader = Routes.loaderForResource(resource);
         RouteBuilder builder = loader.load(resource);
 
-        assertThat(loader).isSameAs(RouteLoaders.Groovy);
+        assertThat(loader).isSameAs(RoutesLoaders.Groovy);
         assertThat(builder).isNotNull();
 
         builder.configure();
@@ -97,11 +114,16 @@ public void testLoadGroovy() throws Exception {
 
     @Test(expected = IllegalArgumentException.class)
     public void testResourceWithoutScheme() {
-        RouteLoaders.loaderFor("routes.js");
+        Routes.loaderForResource("routes.js");
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testResourceWithIllegalScheme() {
-        RouteLoaders.loaderFor("http:routes.js");
+        Routes.loaderForResource("http:routes.js");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testUnsupportedLanguage() {
+        Routes.loaderForLanguage("  test");
     }
 }
diff --git a/runtime/jvm/src/test/resources/routes.mytype b/runtime/jvm/src/test/resources/routes.mytype
new file mode 100644
index 0000000..0f5600d
--- /dev/null
+++ b/runtime/jvm/src/test/resources/routes.mytype
@@ -0,0 +1,3 @@
+
+from('timer:tick')
+    .to('log:info')
\ No newline at end of file


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services