Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime: add support for groovy #19

Merged
merged 1 commit into from
Sep 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions runtime/jvm/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@
<artifactId>commons-lang3</artifactId>
<version>${commons-lang.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>${groovy.version}</version>
<optional>true</optional>
</dependency>

<dependency>
<groupId>junit</groupId>
Expand Down
73 changes: 66 additions & 7 deletions runtime/jvm/src/main/java/org/apache/camel/k/jvm/RouteLoaders.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
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.function.Function;
Expand All @@ -27,20 +28,23 @@
import javax.script.ScriptEngineManager;
import javax.script.SimpleBindings;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.util.DelegatingScript;
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;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.joor.Reflect;

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));
return !isScripting(resource) && hasSupportedScheme(resource);
}

@Override
Expand All @@ -58,8 +62,7 @@ public RouteBuilder load(String resource) throws Exception {
JavaSource {
@Override
public boolean test(String resource) {
return resource.endsWith(".java")
&& (resource.startsWith(Application.SCHEME_CLASSPATH) || resource.startsWith(Application.SCHEME_FILE));
return isScripting(resource, "java") && hasSupportedScheme(resource);
}

@Override
Expand All @@ -76,8 +79,7 @@ public RouteBuilder load(String resource) throws Exception {
JavaScript {
@Override
public boolean test(String resource) {
return resource.endsWith(".js")
&& (resource.startsWith(Application.SCHEME_CLASSPATH) || resource.startsWith(Application.SCHEME_FILE));
return isScripting(resource, "js") && hasSupportedScheme(resource);
}

@Override
Expand All @@ -102,8 +104,36 @@ public void configure() throws Exception {
}
};
}
};
},
Groovy {
@Override
public boolean test(String resource) {
return isScripting(resource, "groovy") && hasSupportedScheme(resource);
}

@Override
public RouteBuilder load(String resource) throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
CompilerConfiguration cc = new CompilerConfiguration();
cc.setScriptBaseClass(DelegatingScript.class.getName());

ClassLoader cl = Thread.currentThread().getContextClassLoader();
GroovyShell sh = new GroovyShell(cl, new Binding(), cc);

try (InputStream is = is(resource)) {
Reader reader = new InputStreamReader(is);
DelegatingScript script = (DelegatingScript) sh.parse(reader);

// set the delegate target
script.setDelegate(new ScriptingDsl(this));
script.run();
}
}
};
}
};

// ********************************
//
Expand All @@ -112,6 +142,18 @@ 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)) {
Expand Down Expand Up @@ -160,4 +202,21 @@ public Component make(String scheme, String type) {
return instance;
}
}

private static class ScriptingDsl {
private final RouteBuilder builder;

public final CamelContext context;
public final Components components;

public ScriptingDsl(RouteBuilder builder) {
this.builder = builder;
this.context = builder.getContext();
this.components = new Components(builder.getContext());
}

public RouteDefinition from(String endpoint) {
return builder.from(endpoint);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ public void testLoadClass() throws Exception {
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
Expand All @@ -60,11 +59,10 @@ public void testLoadJava() throws Exception {
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 {
public void testLoadJavaScript() throws Exception {
String resource = "classpath:/routes.js";
RoutesLoader loader = RouteLoaders.loaderFor(resource);
RouteBuilder builder = loader.load(resource);
Expand All @@ -80,6 +78,23 @@ public void testLoadScript() throws Exception {
assertThat(routes.get(0).getOutputs().get(0)).isInstanceOf(ToDefinition.class);
}

@Test
public void testLoadGroovy() throws Exception {
String resource = "classpath:/routes.groovy";
RoutesLoader loader = RouteLoaders.loaderFor(resource);
RouteBuilder builder = loader.load(resource);

assertThat(loader).isSameAs(RouteLoaders.Groovy);
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");
Expand Down
3 changes: 3 additions & 0 deletions runtime/jvm/src/test/resources/routes.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

from('timer:tick')
.to('log:info')
1 change: 1 addition & 0 deletions runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<assertj.version>3.11.1</assertj.version>
<log4j2.version>2.11.0</log4j2.version>
<slf4j.version>1.7.25</slf4j.version>
<groovy.version>2.5.2</groovy.version>

<fabric8-maven-plugin.version>3.5.40</fabric8-maven-plugin.version>
</properties>
Expand Down