You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pp...@apache.org on 2020/12/03 11:23:41 UTC
[camel] branch master updated: csimple language: support fully
pre-compiled use case
This is an automated email from the ASF dual-hosted git repository.
ppalaga pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/master by this push:
new 8f332aa csimple language: support fully pre-compiled use case
8f332aa is described below
commit 8f332aa8d5c22c56208504f30631a21be8858273
Author: Peter Palaga <pp...@redhat.com>
AuthorDate: Tue Dec 1 22:40:47 2020 +0100
csimple language: support fully pre-compiled use case
---
.../camel/language/csimple/CSimpleLanguage.java | 349 +++++++++++++--------
1 file changed, 217 insertions(+), 132 deletions(-)
diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleLanguage.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleLanguage.java
index 2ff2ca6..4c8eec4 100644
--- a/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleLanguage.java
+++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleLanguage.java
@@ -20,7 +20,9 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -49,19 +51,34 @@ public class CSimpleLanguage extends LanguageSupport implements StaticService {
private static final Logger LOG = LoggerFactory.getLogger(CSimpleLanguage.class);
- private final Map<String, CSimpleExpression> compiled = new ConcurrentHashMap<>();
- private CSimpleCompiler compiler;
+ private final Map<String, CSimpleExpression> compiled;
+ /**
+ * If set, this implementation attempts to compile those expressions at runtime, that are not yet available in
+ * {@link #compiled}; otherwise no compilation attempts will be made at runtime
+ */
+ private final CompilationSupport compilationSupport;
- private String configResource = "camel-csimple.properties";
- private Set<String> imports = new TreeSet<>();
- private Map<String, String> aliases = new HashMap<>();
+ public CSimpleLanguage() {
+ this.compiled = new ConcurrentHashMap<>();
+ this.compilationSupport = new CompilationSupport();
+ }
+
+ /**
+ * For 100% pre-compiled use cases
+ *
+ * @param compiled the compiled
+ */
+ private CSimpleLanguage(Map<String, CSimpleExpression> compiled) {
+ this.compiled = compiled;
+ this.compilationSupport = null;
+ }
public String getConfigResource() {
- return configResource;
+ return compilationSupport().configResource;
}
public void setConfigResource(String configResource) {
- this.configResource = configResource;
+ compilationSupport().configResource = configResource;
}
/**
@@ -70,14 +87,7 @@ public class CSimpleLanguage extends LanguageSupport implements StaticService {
* @param imports import such as com.foo.MyClass
*/
public void addImport(String imports) {
- if (!imports.startsWith("import ")) {
- imports = "import " + imports;
- }
- if (compiler != null) {
- compiler.addImport(imports);
- } else {
- this.imports.add(imports);
- }
+ compilationSupport().addImport(imports);
}
/**
@@ -87,132 +97,27 @@ public class CSimpleLanguage extends LanguageSupport implements StaticService {
* @param value the value
*/
public void addAliases(String key, String value) {
- if (compiler != null) {
- compiler.addAliases(key, value);
- } else {
- this.aliases.put(key, value);
- }
+ compilationSupport().addAliases(key, value);
}
@Override
public void init() {
- // load pre compiled first
- loadPreCompiled();
-
- // load optional configuration file
- loadConfiguration();
-
- // detect custom compiler (camel-csimple-joor)
- ExtendedCamelContext ecc = getCamelContext().adapt(ExtendedCamelContext.class);
- Optional<Class<?>> clazz = ecc.getBootstrapFactoryFinder().findClass(CSimpleCompiler.FACTORY);
- if (clazz.isPresent()) {
- compiler = (CSimpleCompiler) ecc.getInjector().newInstance(clazz.get(), false);
- if (compiler != null) {
- LOG.info("Detected camel-csimple-joor compiler");
- if (imports != null) {
- imports.forEach(compiler::addImport);
- }
- if (aliases != null) {
- aliases.forEach(compiler::addAliases);
- }
- }
- ServiceHelper.initService(compiler);
+ if (compilationSupport != null) {
+ compilationSupport.init();
}
}
@Override
public void start() {
- ServiceHelper.startService(compiler);
+ if (compilationSupport != null) {
+ ServiceHelper.startService(compilationSupport.compiler);
+ }
}
@Override
public void stop() {
- ServiceHelper.stopService(compiler);
- }
-
- private void loadPreCompiled() {
- ExtendedCamelContext ecc = getCamelContext().adapt(ExtendedCamelContext.class);
- InputStream is = ecc.getClassResolver().loadResourceAsStream(PRE_COMPILED_FILE);
- if (is != null) {
- try {
- String text = IOHelper.loadText(is);
- String[] lines = text.split("\n");
- for (String fqn : lines) {
- // skip comments
- fqn = fqn.trim();
- if (fqn.startsWith("#") || fqn.isEmpty()) {
- continue;
- }
- // load class
- Class<CSimpleExpression> clazz = ecc.getClassResolver().resolveMandatoryClass(fqn, CSimpleExpression.class);
- CSimpleExpression ce = clazz.getConstructor(CamelContext.class).newInstance(getCamelContext());
- compiled.put(ce.getText(), ce);
- }
- } catch (Exception e) {
- throw new RuntimeCamelException("Error initializing csimple language", e);
- } finally {
- IOHelper.close(is);
- }
- if (!compiled.isEmpty()) {
- LOG.info("Loaded and initialized {} csimple expressions from classpath", compiled.size());
- }
- }
- }
-
- private void loadConfiguration() {
- InputStream is;
- String loaded;
- is = getCamelContext().getClassResolver().loadResourceAsStream(CONFIG_FILE);
- try {
- if (is == null) {
- // load from file system
- File file = new File(configResource);
- if (file.exists()) {
- is = new FileInputStream(file);
- }
- }
- if (is == null) {
- return;
- }
- loaded = IOHelper.loadText(is);
- } catch (IOException e) {
- throw new RuntimeCamelException("Cannot load " + CONFIG_FILE + " from classpath");
-
- }
- IOHelper.close(is);
-
- int counter1 = 0;
- int counter2 = 0;
- String[] lines = loaded.split("\n");
- for (String line : lines) {
- line = line.trim();
- // skip comments
- if (line.startsWith("#")) {
- continue;
- }
- // imports
- if (line.startsWith("import ")) {
- imports.add(line);
- counter1++;
- continue;
- }
- // aliases as key=value
- String key = StringHelper.before(line, "=");
- String value = StringHelper.after(line, "=");
- if (key != null) {
- key = key.trim();
- }
- if (value != null) {
- value = value.trim();
- }
- if (key != null && value != null) {
- this.aliases.put(key, value);
- counter2++;
- }
- }
- if (counter1 > 0 || counter2 > 0) {
- LOG.info("Loaded csimple language imports: {} and aliases: {} from configuration: {}", counter1, counter2,
- configResource);
+ if (compilationSupport != null) {
+ ServiceHelper.stopService(compilationSupport.compiler);
}
}
@@ -226,8 +131,8 @@ public class CSimpleLanguage extends LanguageSupport implements StaticService {
text = text.trim();
Predicate answer = compiled.get(text);
- if (answer == null && compiler != null) {
- CSimpleExpression exp = compiler.compilePredicate(getCamelContext(), expression);
+ if (answer == null && compilationSupport != null) {
+ CSimpleExpression exp = compilationSupport.compilePredicate(getCamelContext(), expression);
if (exp != null) {
compiled.put(text, exp);
answer = exp;
@@ -249,8 +154,8 @@ public class CSimpleLanguage extends LanguageSupport implements StaticService {
text = text.trim();
Expression answer = compiled.get(text);
- if (answer == null && compiler != null) {
- CSimpleExpression exp = compiler.compileExpression(getCamelContext(), expression);
+ if (answer == null && compilationSupport != null) {
+ CSimpleExpression exp = compilationSupport.compileExpression(getCamelContext(), expression);
if (exp != null) {
compiled.put(text, exp);
answer = exp;
@@ -262,4 +167,184 @@ public class CSimpleLanguage extends LanguageSupport implements StaticService {
return answer;
}
+ private CompilationSupport compilationSupport() {
+ if (compilationSupport == null) {
+ throw new IllegalStateException(
+ "Runtime Compilation is not supported with this " + CSimpleLanguage.class.getSimpleName());
+ }
+ return compilationSupport;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private Map<String, CSimpleExpression> compiled = new LinkedHashMap<String, CSimpleExpression>();
+
+ public CSimpleLanguage build() {
+ final Map<String, CSimpleExpression> cmpl = Collections.unmodifiableMap(compiled);
+ compiled = null; // invalidate the builder to prevent leaking the mutable collection
+ return new CSimpleLanguage(cmpl);
+ }
+
+ public Builder expression(CSimpleExpression expression) {
+ compiled.put(expression.getText(), expression);
+ return this;
+ }
+ }
+
+ class CompilationSupport {
+ private CSimpleCompiler compiler;
+ private String configResource = "camel-csimple.properties";
+ private final Set<String> imports = new TreeSet<>();
+ private final Map<String, String> aliases = new HashMap<>();
+
+ public void addImport(String imports) {
+ if (!imports.startsWith("import ")) {
+ imports = "import " + imports;
+ }
+ if (compiler != null) {
+ compiler.addImport(imports);
+ } else {
+ this.imports.add(imports);
+ }
+ }
+
+ public void init() {
+ // load pre compiled first
+ loadPreCompiled();
+
+ // load optional configuration file
+ loadConfiguration();
+
+ // detect custom compiler (camel-csimple-joor)
+ ExtendedCamelContext ecc = getCamelContext().adapt(ExtendedCamelContext.class);
+ Optional<Class<?>> clazz = ecc.getBootstrapFactoryFinder().findClass(CSimpleCompiler.FACTORY);
+ if (clazz.isPresent()) {
+ compiler = (CSimpleCompiler) ecc.getInjector().newInstance(clazz.get(), false);
+ if (compiler != null) {
+ LOG.info("Detected camel-csimple-joor compiler");
+ if (imports != null) {
+ imports.forEach(compiler::addImport);
+ }
+ if (aliases != null) {
+ aliases.forEach(compiler::addAliases);
+ }
+ }
+ ServiceHelper.initService(compiler);
+ }
+ }
+
+ public CSimpleExpression compilePredicate(CamelContext camelContext, String expression) {
+ if (compiler != null) {
+ return compiler.compilePredicate(camelContext, expression);
+ }
+ return null;
+ }
+
+ public CSimpleExpression compileExpression(CamelContext camelContext, String expression) {
+ if (compiler != null) {
+ return compiler.compileExpression(camelContext, expression);
+ }
+ return null;
+ }
+
+ public void addAliases(String key, String value) {
+ if (compiler != null) {
+ compiler.addAliases(key, value);
+ } else {
+ this.aliases.put(key, value);
+ }
+ }
+
+ private void loadPreCompiled() {
+ ExtendedCamelContext ecc = getCamelContext().adapt(ExtendedCamelContext.class);
+ InputStream is = ecc.getClassResolver().loadResourceAsStream(PRE_COMPILED_FILE);
+ if (is != null) {
+ try {
+ String text = IOHelper.loadText(is);
+ String[] lines = text.split("\n");
+ for (String fqn : lines) {
+ // skip comments
+ fqn = fqn.trim();
+ if (fqn.startsWith("#") || fqn.isEmpty()) {
+ continue;
+ }
+ // load class
+ Class<CSimpleExpression> clazz
+ = ecc.getClassResolver().resolveMandatoryClass(fqn, CSimpleExpression.class);
+ CSimpleExpression ce = clazz.getConstructor(CamelContext.class).newInstance(getCamelContext());
+ compiled.put(ce.getText(), ce);
+ }
+ } catch (Exception e) {
+ throw new RuntimeCamelException("Error initializing csimple language", e);
+ } finally {
+ IOHelper.close(is);
+ }
+ if (!compiled.isEmpty()) {
+ LOG.info("Loaded and initialized {} csimple expressions from classpath", compiled.size());
+ }
+ }
+ }
+
+ private void loadConfiguration() {
+ InputStream is;
+ String loaded;
+ is = getCamelContext().getClassResolver().loadResourceAsStream(CONFIG_FILE);
+ try {
+ if (is == null) {
+ // load from file system
+ File file = new File(configResource);
+ if (file.exists()) {
+ is = new FileInputStream(file);
+ }
+ }
+ if (is == null) {
+ return;
+ }
+ loaded = IOHelper.loadText(is);
+ } catch (IOException e) {
+ throw new RuntimeCamelException("Cannot load " + CONFIG_FILE + " from classpath");
+
+ }
+ IOHelper.close(is);
+
+ int counter1 = 0;
+ int counter2 = 0;
+ String[] lines = loaded.split("\n");
+ for (String line : lines) {
+ line = line.trim();
+ // skip comments
+ if (line.startsWith("#")) {
+ continue;
+ }
+ // imports
+ if (line.startsWith("import ")) {
+ imports.add(line);
+ counter1++;
+ continue;
+ }
+ // aliases as key=value
+ String key = StringHelper.before(line, "=");
+ String value = StringHelper.after(line, "=");
+ if (key != null) {
+ key = key.trim();
+ }
+ if (value != null) {
+ value = value.trim();
+ }
+ if (key != null && value != null) {
+ this.aliases.put(key, value);
+ counter2++;
+ }
+ }
+ if (counter1 > 0 || counter2 > 0) {
+ LOG.info("Loaded csimple language imports: {} and aliases: {} from configuration: {}", counter1, counter2,
+ configResource);
+ }
+ }
+
+ }
+
}