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/07 12:20:36 UTC

[GitHub] nicolaferraro closed pull request #1: Add support for .js, .java and classes

nicolaferraro closed pull request #1: Add support for .js, .java and classes
URL: https://github.com/apache/camel-k/pull/1
 
 
   

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/runtime/jvm/pom.xml b/runtime/jvm/pom.xml
index 27cfe06..f4860c6 100644
--- a/runtime/jvm/pom.xml
+++ b/runtime/jvm/pom.xml
@@ -26,6 +26,17 @@
             <artifactId>log4j-slf4j-impl</artifactId>
             <version>${log4j2.version}</version>
         </dependency>
+        <dependency>
+            <groupId>net.openhft</groupId>
+            <artifactId>compiler</artifactId>
+            <version>${openhft-compiler.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.6</version>
+        </dependency>
 
         <dependency>
             <groupId>junit</groupId>
@@ -33,6 +44,13 @@
             <version>${junit.version}</version>
             <scope>test</scope>
         </dependency>
+
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <version>${assertj.version}</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
 </project>
\ No newline at end of file
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 ad7c54a..90d3f4d 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
@@ -1,18 +1,48 @@
+/**
+ * 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;
 
-public class Application {
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.main.Main;
 
-    public static final String ENV_KAMEL_CLASS = "KAMEL_CLASS";
+public class Application {
+    public static final String ENV_KAMEL_ROUTES_URI = "KAMEL_ROUTES_PATH";
+    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_KAMEL_ROUTES_URI);
 
-        String clsName = System.getenv(ENV_KAMEL_CLASS);
-        if (clsName == null || clsName.trim().length() == 0) {
-            throw new IllegalStateException("No valid class found in " + ENV_KAMEL_CLASS + " environment variable");
+        if (resource == null || resource.trim().length() == 0) {
+            throw new IllegalStateException("No valid resource found in " + ENV_KAMEL_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);
         }
 
-        Runner runner = new Runner();
-        runner.run(clsName);
-    }
+        RoutesLoader loader = RouteLoaders.loaderFor(resource);
+        RouteBuilder routes = loader.load(resource);
 
+        if (routes == null) {
+            throw new IllegalStateException("Unable to load route from: " + resource);
+        }
+
+        Main main = new Main();
+        main.addRouteBuilder(routes);
+        main.run();
+    }
 }
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/RouteLoaders.java
new file mode 100644
index 0000000..0eb12fa
--- /dev/null
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RouteLoaders.java
@@ -0,0 +1,170 @@
+/**
+ * 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.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.function.Function;
+import javax.script.Bindings;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.SimpleBindings;
+
+import net.openhft.compiler.CompilerUtils;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Component;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.RouteDefinition;
+import org.apache.commons.io.IOUtils;
+
+public enum RouteLoaders implements RoutesLoader {
+    JavaClass {
+        @Override
+        public boolean test(String resource) {
+            return !resource.endsWith(".java") && !resource.endsWith(".js")
+                && (resource.startsWith(Application.SCHEME_CLASSPATH) || resource.startsWith(Application.SCHEME_FILE));
+        }
+
+        @Override
+        public RouteBuilder load(String resource) throws Exception {
+            String path = resource.substring(Application.SCHEME_CLASSPATH.length());
+            Class<?> type = Class.forName(path);
+
+            if (!RouteBuilder.class.isAssignableFrom(type)) {
+                throw new IllegalStateException("The class provided (" + path + ") is not a org.apache.camel.builder.RouteBuilder");
+            }
+
+            return (RouteBuilder)type.newInstance();
+        }
+    },
+    JavaSource {
+        @Override
+        public boolean test(String resource) {
+            return resource.endsWith(".java")
+                && (resource.startsWith(Application.SCHEME_CLASSPATH) || resource.startsWith(Application.SCHEME_FILE));
+        }
+
+        @Override
+        public RouteBuilder load(String resource) throws Exception {
+            try (InputStream is = is(resource)) {
+                String name = resource.substring(0, resource.length() - ".java".length()).split(":", -1)[1];
+                if (name.startsWith("/")) {
+                    name = name.substring(1);
+                }
+
+                String content = IOUtils.toString(is);
+
+                Class<?> type = CompilerUtils.CACHED_COMPILER.loadFromJava(name.replace("/", "."), content);
+                if (!RouteBuilder.class.isAssignableFrom(type)) {
+                    throw new IllegalStateException("The class provided (" + resource + ") is not a org.apache.camel.builder.RouteBuilder");
+                }
+
+                return (RouteBuilder) type.newInstance();
+            }
+        }
+    },
+    JavaScript {
+        @Override
+        public boolean test(String resource) {
+            return resource.endsWith(".js")
+                && (resource.startsWith(Application.SCHEME_CLASSPATH) || resource.startsWith(Application.SCHEME_FILE));
+        }
+
+        @Override
+        public RouteBuilder load(String resource) throws Exception {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    final CamelContext context = getContext();
+                    final ScriptEngineManager manager = new ScriptEngineManager();
+                    final ScriptEngine engine = manager.getEngineByName("nashorn");
+                    final Bindings bindings = new SimpleBindings();
+
+                    // Exposed to the underlying script, but maybe better to have
+                    // a nice dsl
+                    bindings.put("context", context);
+                    bindings.put("components", context);
+                    bindings.put("from", (Function<String, RouteDefinition>) uri -> from(uri));
+
+                    try (InputStream is = is(resource)) {
+                        engine.eval(new InputStreamReader(is), bindings);
+                    }
+                }
+            };
+        }
+    };
+
+
+    // ********************************
+    //
+    // Helpers
+    //
+    // TODO: move to a dedicate class
+    // ********************************
+
+    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)) {
+            return Application.class.getResourceAsStream(
+                resource.substring(Application.SCHEME_CLASSPATH.length())
+            );
+        } else {
+            return Files.newInputStream(
+                Paths.get(resource.substring(Application.SCHEME_FILE.length()))
+            );
+        }
+    }
+
+    public static class Components {
+        private CamelContext context;
+
+        public Components(CamelContext context) {
+            this.context = context;
+        }
+
+        public Component get(String scheme) {
+            return context.getComponent(scheme, true);
+        }
+
+        public Component put(String scheme, Component instance) {
+            context.addComponent(scheme, instance);
+
+            return instance;
+        }
+
+        public Component make(String scheme, String type) {
+            final Class<?> clazz = context.getClassResolver().resolveClass(type);
+            final Component instance = (Component)context.getInjector().newInstance(clazz);
+
+            context.addComponent(scheme, instance);
+
+            return instance;
+        }
+    }
+}
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
new file mode 100644
index 0000000..9589822
--- /dev/null
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RoutesLoader.java
@@ -0,0 +1,25 @@
+/**
+ * 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.util.function.Predicate;
+
+import org.apache.camel.builder.RouteBuilder;
+
+public interface RoutesLoader extends Predicate<String> {
+    RouteBuilder load(String resource) throws Exception;
+}
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Runner.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Runner.java
deleted file mode 100644
index 7b1a58c..0000000
--- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Runner.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.apache.camel.k.jvm;
-
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.main.Main;
-
-import java.util.Objects;
-
-public class Runner {
-
-    public void run(String className) throws Exception {
-        Objects.requireNonNull(className, "className must be present");
-
-        Class<?> cls = Class.forName(className);
-        Object instance = cls.newInstance();
-        if (!RouteBuilder.class.isInstance(instance)) {
-            throw new IllegalStateException("The class provided (" + className + ") is not a org.apache.camel.builder.RouteBuilder");
-        }
-
-        RouteBuilder builder = (RouteBuilder) instance;
-
-        Main main = new Main();
-        main.addRouteBuilder(builder);
-        main.run();
-    }
-
-}
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 39c6c7d..e43d711 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
@@ -4,12 +4,10 @@
 import org.junit.Test;
 
 public class ApplicationTest {
-
     @Test
     @Ignore
     public void applicationTest() throws Exception {
-        Runner runner = new Runner();
-        runner.run(MyRoutes.class.getCanonicalName());
+        Application.main(new String[] { MyRoutes.class.getCanonicalName() });
     }
 
 }
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/RouteLoadersTest.java
new file mode 100644
index 0000000..f9cf4c7
--- /dev/null
+++ b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/RouteLoadersTest.java
@@ -0,0 +1,92 @@
+/**
+ * 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.util.List;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.model.ToDefinition;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class RouteLoadersTest {
+
+    @Test
+    public void testLoadClass() throws Exception {
+        String resource = "classpath:" + MyRoutes.class.getCanonicalName();
+        RoutesLoader loader = RouteLoaders.loaderFor(resource);
+        RouteBuilder builder = loader.load(resource);
+
+        assertThat(loader).isSameAs(RouteLoaders.JavaClass);
+        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);
+        assertThat(routes.get(0).getOutputs().get(0)).isInstanceOf(ToDefinition.class);
+    }
+
+    @Test
+    public void testLoadJava() throws Exception {
+        String resource = "classpath:/MyRoutes.java";
+        RoutesLoader loader = RouteLoaders.loaderFor(resource);
+        RouteBuilder builder = loader.load(resource);
+
+        assertThat(loader).isSameAs(RouteLoaders.JavaSource);
+        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);
+        assertThat(routes.get(0).getOutputs().get(0)).isInstanceOf(ToDefinition.class);
+    }
+
+    @Test
+    public void testLoadScript() throws Exception {
+        String resource = "classpath:/routes.js";
+        RoutesLoader loader = RouteLoaders.loaderFor(resource);
+        RouteBuilder builder = loader.load(resource);
+
+        assertThat(loader).isSameAs(RouteLoaders.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(expected = IllegalArgumentException.class)
+    public void testResourceWithoutScheme() {
+        RouteLoaders.loaderFor("routes.js");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testResourceWithIllegalScheme() {
+        RouteLoaders.loaderFor("http:routes.js");
+    }
+}
diff --git a/runtime/jvm/src/test/resources/MyRoutes.java b/runtime/jvm/src/test/resources/MyRoutes.java
new file mode 100644
index 0000000..217d80c
--- /dev/null
+++ b/runtime/jvm/src/test/resources/MyRoutes.java
@@ -0,0 +1,9 @@
+import org.apache.camel.builder.RouteBuilder;
+
+public class MyRoutes extends RouteBuilder {
+    @Override
+    public void configure() throws Exception {
+        from("timer:tick")
+                .to("log:info");
+    }
+}
\ No newline at end of file
diff --git a/runtime/jvm/src/test/resources/routes.js b/runtime/jvm/src/test/resources/routes.js
new file mode 100644
index 0000000..0f5600d
--- /dev/null
+++ b/runtime/jvm/src/test/resources/routes.js
@@ -0,0 +1,3 @@
+
+from('timer:tick')
+    .to('log:info')
\ No newline at end of file
diff --git a/runtime/pom.xml b/runtime/pom.xml
index 3987857..ee1f82d 100644
--- a/runtime/pom.xml
+++ b/runtime/pom.xml
@@ -10,11 +10,15 @@
     <packaging>pom</packaging>
 
     <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
 
         <camel.version>2.22.0</camel.version>
         <junit.version>4.12</junit.version>
+        <openhft-compiler.version>2.3.1</openhft-compiler.version>
+        <assertj.version>3.11.1</assertj.version>
         <log4j2.version>2.11.0</log4j2.version>
         <slf4j.version>1.7.25</slf4j.version>
 
@@ -48,5 +52,5 @@
     <modules>
         <module>jvm</module>
     </modules>
-    
+
 </project>
\ 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