You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2022/04/27 17:39:53 UTC
[camel] 02/02: CAMEL-18081: camel-main/camel-java-dsl - Add option to compile to disk to pre-load on next run
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
commit e9064257c793af050108570ee7124e10dd96e6b2
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Apr 27 19:39:31 2022 +0200
CAMEL-18081: camel-main/camel-java-dsl - Add option to compile to disk to pre-load on next run
---
.../org/apache/camel/spi/RoutesBuilderLoader.java | 7 ---
.../java/org/apache/camel/spi/RoutesLoader.java | 9 +++
.../camel/impl/engine/DefaultRoutesLoader.java | 10 +--
.../dsl/java/joor/ClassRoutesBuilderLoader.java | 2 +
.../dsl/java/joor/JavaRoutesBuilderLoader.java | 49 +++++++++++++++
.../dsl/java/joor/JavaJoorSaveToDiskTest.java | 71 ++++++++++++++++++++++
6 files changed, 133 insertions(+), 15 deletions(-)
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/RoutesBuilderLoader.java b/core/camel-api/src/main/java/org/apache/camel/spi/RoutesBuilderLoader.java
index 3f11b1350f6..379ab0ced16 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/RoutesBuilderLoader.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/RoutesBuilderLoader.java
@@ -64,11 +64,4 @@ public interface RoutesBuilderLoader extends StaticService, CamelContextAware {
// noop
}
- /**
- * Optional initializes the routes loader from the given set of options
- *
- * @param options options as key values
- */
- default void init(Map<String, Object> options) {
- }
}
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/RoutesLoader.java b/core/camel-api/src/main/java/org/apache/camel/spi/RoutesLoader.java
index 38b9bc5a9ad..d2e09295299 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/RoutesLoader.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/RoutesLoader.java
@@ -34,6 +34,15 @@ public interface RoutesLoader extends CamelContextAware {
*/
String FACTORY = "routes-loader";
+ /**
+ * Looks up a {@link RoutesBuilderLoader} in the registry or fallback to a factory finder mechanism if none found.
+ *
+ * @param extension the file extension for which a loader should be found.
+ * @return a {@link RoutesBuilderLoader}
+ * @throws IllegalArgumentException if no {@link RoutesBuilderLoader} can be found for the given file extension
+ */
+ RoutesBuilderLoader getRoutesLoader(String extension) throws Exception;
+
/**
* Loads {@link RoutesBuilder} from the give list of {@link Resource} into the current
* {@link org.apache.camel.CamelContext}.
diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesLoader.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesLoader.java
index 7c2063a6cdf..1e3506621e0 100644
--- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesLoader.java
+++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultRoutesLoader.java
@@ -137,14 +137,8 @@ public class DefaultRoutesLoader extends ServiceSupport implements RoutesLoader,
resolveRoutesBuilderLoader(resource).preParseRoute(resource);
}
- /**
- * Looks up a {@link RoutesBuilderLoader} in the registry or fallback to a factory finder mechanism if none found.
- *
- * @param extension the file extension for which a loader should be find.
- * @return a {@link RoutesBuilderLoader}
- * @throws IllegalArgumentException if no {@link RoutesBuilderLoader} can be found for the given file extension
- */
- protected RoutesBuilderLoader getRoutesLoader(String extension) throws Exception {
+ @Override
+ public RoutesBuilderLoader getRoutesLoader(String extension) throws Exception {
RoutesBuilderLoader answer = getCamelContext().getRegistry().lookupByNameAndType(
ROUTES_LOADER_KEY_PREFIX + extension,
RoutesBuilderLoader.class);
diff --git a/dsl/camel-java-joor-dsl/src/main/java/org/apache/camel/dsl/java/joor/ClassRoutesBuilderLoader.java b/dsl/camel-java-joor-dsl/src/main/java/org/apache/camel/dsl/java/joor/ClassRoutesBuilderLoader.java
index 4ee1488b429..b216f220d3d 100644
--- a/dsl/camel-java-joor-dsl/src/main/java/org/apache/camel/dsl/java/joor/ClassRoutesBuilderLoader.java
+++ b/dsl/camel-java-joor-dsl/src/main/java/org/apache/camel/dsl/java/joor/ClassRoutesBuilderLoader.java
@@ -51,6 +51,8 @@ public class ClassRoutesBuilderLoader extends ExtendedRouteBuilderLoaderSupport
protected Collection<RoutesBuilder> doLoadRoutesBuilders(Collection<Resource> resources) throws Exception {
Collection<RoutesBuilder> answer = new ArrayList<>();
+ LOG.debug("Loading .class resources from: {}", resources);
+
// load all the byte code first from the resources
Map<String, byte[]> byteCodes = new LinkedHashMap<>();
for (Resource res : resources) {
diff --git a/dsl/camel-java-joor-dsl/src/main/java/org/apache/camel/dsl/java/joor/JavaRoutesBuilderLoader.java b/dsl/camel-java-joor-dsl/src/main/java/org/apache/camel/dsl/java/joor/JavaRoutesBuilderLoader.java
index 167d751ca74..b4d95cd6148 100644
--- a/dsl/camel-java-joor-dsl/src/main/java/org/apache/camel/dsl/java/joor/JavaRoutesBuilderLoader.java
+++ b/dsl/camel-java-joor-dsl/src/main/java/org/apache/camel/dsl/java/joor/JavaRoutesBuilderLoader.java
@@ -20,21 +20,26 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
+import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.camel.CamelContextAware;
+import org.apache.camel.ExtendedCamelContext;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.api.management.ManagedResource;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.dsl.support.ExtendedRouteBuilderLoaderSupport;
import org.apache.camel.spi.CompilePostProcessor;
+import org.apache.camel.spi.ExtendedRoutesBuilderLoader;
import org.apache.camel.spi.Resource;
import org.apache.camel.spi.ResourceAware;
+import org.apache.camel.spi.RoutesBuilderLoader;
import org.apache.camel.spi.annotations.RoutesLoader;
import org.apache.camel.support.ResourceHelper;
import org.apache.camel.support.RouteWatcherReloadStrategy;
@@ -57,6 +62,17 @@ public class JavaRoutesBuilderLoader extends ExtendedRouteBuilderLoaderSupport {
super(EXTENSION);
}
+ @Override
+ protected RouteBuilder doLoadRouteBuilder(Resource resource) throws Exception {
+ Collection<RoutesBuilder> answer = doLoadRoutesBuilders(List.of(resource));
+ if (answer.size() == 1) {
+ RoutesBuilder builder = answer.iterator().next();
+ return (RouteBuilder) builder;
+ }
+
+ return super.doLoadRouteBuilder(resource);
+ }
+
@Override
protected Collection<RoutesBuilder> doLoadRoutesBuilders(Collection<Resource> resources) throws Exception {
Collection<RoutesBuilder> answer = new ArrayList<>();
@@ -78,6 +94,14 @@ public class JavaRoutesBuilderLoader extends ExtendedRouteBuilderLoaderSupport {
}
}
+ if (getCompileDirectory() != null && isCompileLoadFirst()) {
+ resources = doLoadCompiledFirst(nameToResource, answer);
+ if (resources.isEmpty()) {
+ // all resources are loaded from pre-compiled
+ return answer;
+ }
+ }
+
LOG.debug("Compiling unit: {}", unit);
CompilationUnit.Result result = MultiCompile.compileUnit(unit);
@@ -129,6 +153,31 @@ public class JavaRoutesBuilderLoader extends ExtendedRouteBuilderLoaderSupport {
return answer;
}
+ private Collection<Resource> doLoadCompiledFirst(Map<String, Resource> nameToResource, Collection<RoutesBuilder> answer) throws Exception {
+ // look for existing compiled and load them first, and any that are missing is to be compiled
+ Collection<Resource> toBeCompiled = new ArrayList<>();
+
+ Collection<Resource> byteCodes = new ArrayList<>();
+ for (String className : nameToResource.keySet()) {
+ File source = new File(getCompileDirectory() + "/" + className + ".class");
+ if (source.exists()) {
+ byte[] code = Files.readAllBytes(source.toPath());
+ byteCodes.add(ResourceHelper.fromBytes("class:" + className + ".class", code));
+ } else {
+ toBeCompiled.add(nameToResource.get(className));
+ }
+ }
+ if (!byteCodes.isEmpty()) {
+ // use the loader that can load from class byte codes
+ ExtendedRoutesBuilderLoader loader = (ExtendedRoutesBuilderLoader) getCamelContext().adapt(ExtendedCamelContext.class)
+ .getRoutesLoader().getRoutesLoader("class");
+ Collection<RoutesBuilder> loaded = loader.loadRoutesBuilders(byteCodes);
+ answer.addAll(loaded);
+ }
+
+ return toBeCompiled;
+ }
+
private static void saveByteCodeToDisk(String outputDirectory, String name, byte[] byteCode) {
// write to disk (can be triggered multiple times so only write once)
File target = new File(outputDirectory + "/" + name + ".class");
diff --git a/dsl/camel-java-joor-dsl/src/test/java/org/apache/camel/dsl/java/joor/JavaJoorSaveToDiskTest.java b/dsl/camel-java-joor-dsl/src/test/java/org/apache/camel/dsl/java/joor/JavaJoorSaveToDiskTest.java
new file mode 100644
index 00000000000..a941a335469
--- /dev/null
+++ b/dsl/camel-java-joor-dsl/src/test/java/org/apache/camel/dsl/java/joor/JavaJoorSaveToDiskTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.dsl.java.joor;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.spi.Resource;
+import org.apache.camel.util.FileUtil;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+
+public class JavaJoorSaveToDiskTest {
+
+ @Test
+ public void testSaveToDisk() throws Exception {
+ FileUtil.removeDir(new File("target/compiled"));
+
+ try (DefaultCamelContext context = new DefaultCamelContext()) {
+ context.start();
+
+ JavaRoutesBuilderLoader loader = new JavaRoutesBuilderLoader();
+ loader.setCamelContext(context);
+ loader.setCompileDirectory("target/compiled");
+ loader.start();
+
+ Resource resource = context.getResourceLoader().resolveResource("/routes/MyMockRoute.java");
+ RouteBuilder builder = (RouteBuilder) loader.loadRoutesBuilder(resource);
+
+ builder.setCamelContext(context);
+ builder.configure();
+ }
+
+ // should have saved to disk
+ Assertions.assertTrue(new File("target/compiled/MyMockRoute.class").exists());
+
+ // should be able to load from disk
+ try (DefaultCamelContext context = new DefaultCamelContext()) {
+ context.start();
+
+ JavaRoutesBuilderLoader loader = new JavaRoutesBuilderLoader();
+ loader.setCamelContext(context);
+ loader.setCompileDirectory("target/compiled");
+ loader.setCompileLoadFirst(true);
+ loader.start();
+
+ Resource resource = context.getResourceLoader().resolveResource("/routes/MyMockRoute.java");
+ RouteBuilder builder = (RouteBuilder) loader.loadRoutesBuilder(resource);
+
+ builder.setCamelContext(context);
+ builder.configure();
+ }
+
+ }
+
+}