use of io.quarkus.bootstrap.classloading.QuarkusClassLoader in project camel-quarkus by apache.
the class CSimpleProcessor method collectCSimpleExpressions.
@BuildStep
void collectCSimpleExpressions(CamelConfig config, List<CamelRoutesBuilderClassBuildItem> routesBuilderClasses, BuildProducer<CSimpleExpressionSourceBuildItem> csimpleExpressions) throws ClassNotFoundException {
if (!routesBuilderClasses.isEmpty()) {
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (!(loader instanceof QuarkusClassLoader)) {
throw new IllegalStateException(QuarkusClassLoader.class.getSimpleName() + " expected as the context class loader");
}
final ExpressionCollector collector = new ExpressionCollector(loader);
final CamelContext ctx = new DefaultCamelContext();
for (CamelRoutesBuilderClassBuildItem routesBuilderClass : routesBuilderClasses) {
final String className = routesBuilderClass.getDotName().toString();
final Class<?> cl = loader.loadClass(className);
if (!RouteBuilder.class.isAssignableFrom(cl)) {
LOG.warnf("CSimple language expressions occurring in %s won't be compiled at build time", cl);
} else {
try {
final RouteBuilder rb = (RouteBuilder) cl.getDeclaredConstructor().newInstance();
rb.setCamelContext(ctx);
try {
rb.configure();
collector.collect("csimple", (script, isPredicate) -> csimpleExpressions.produce(new CSimpleExpressionSourceBuildItem(script, isPredicate, className)), rb.getRouteCollection(), rb.getRestCollection());
} catch (Exception e) {
switch(config.csimple.onBuildTimeAnalysisFailure) {
case fail:
throw new RuntimeException("Could not extract CSimple expressions from " + className + ". You may want to set quarkus.camel.csimple.on-build-time-analysis-failure to warn or ignore if you do not use CSimple language in your routes", e);
case warn:
LOG.warnf(e, "Could not extract CSimple language expressions from the route definition %s in class %s.", rb, cl);
break;
case ignore:
LOG.debugf(e, "Could not extract CSimple language expressions from the route definition %s in class %s", rb, cl);
break;
default:
throw new IllegalStateException("Unexpected " + FailureRemedy.class.getSimpleName() + ": " + config.csimple.onBuildTimeAnalysisFailure);
}
}
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
throw new RuntimeException("Could not instantiate " + className, e);
}
}
}
}
}
use of io.quarkus.bootstrap.classloading.QuarkusClassLoader in project camel-quarkus by apache.
the class CamelRestOASFilter method exposeOpenAPI.
@BuildStep(onlyIf = ExposeOpenApiEnabled.class)
void exposeOpenAPI(List<CamelRoutesBuilderClassBuildItem> routesBuilderClasses, BuildProducer<AddToOpenAPIDefinitionBuildItem> openAPI, Capabilities capabilities) throws Exception {
if (capabilities.isPresent(Capability.SMALLRYE_OPENAPI)) {
RoutesConfigurer configurer = new RoutesConfigurer();
List<RoutesBuilder> routes = new ArrayList<>();
configurer.setRoutesBuilders(routes);
configurer.setRoutesCollector(new DefaultRoutesCollector());
configurer.setRoutesIncludePattern(CamelSupport.getOptionalConfigValue("camel.main.routes-include-pattern", String.class, null));
configurer.setRoutesExcludePattern(CamelSupport.getOptionalConfigValue("camel.main.routes-exclude-pattern", String.class, null));
final CamelContext ctx = new DefaultCamelContext();
if (!routesBuilderClasses.isEmpty()) {
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (!(loader instanceof QuarkusClassLoader)) {
throw new IllegalStateException(QuarkusClassLoader.class.getSimpleName() + " expected as the context class loader");
}
for (CamelRoutesBuilderClassBuildItem routesBuilderClass : routesBuilderClasses) {
final String className = routesBuilderClass.getDotName().toString();
final Class<?> cl = loader.loadClass(className);
if (RouteBuilder.class.isAssignableFrom(cl)) {
try {
final RouteBuilder rb = (RouteBuilder) cl.getDeclaredConstructor().newInstance();
routes.add(rb);
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException("Could not instantiate " + className, e);
}
}
}
}
try {
configurer.configureRoutes(ctx);
} catch (Exception e) {
// ignore
LOGGER.warn("config routes failed with " + e);
}
openAPI.produce(new AddToOpenAPIDefinitionBuildItem(new CamelRestOASFilter(ctx)));
}
}
use of io.quarkus.bootstrap.classloading.QuarkusClassLoader in project camel-quarkus by apache.
the class CSimpleProcessor method compileCSimpleExpressions.
@BuildStep
void compileCSimpleExpressions(List<CSimpleExpressionSourceBuildItem> expressionSources, BuildProducer<CompiledCSimpleExpressionBuildItem> compiledCSimpleExpression, BuildProducer<GeneratedClassBuildItem> generatedClasses) throws IOException {
if (!expressionSources.isEmpty()) {
final Set<String> imports = new TreeSet<>();
final Map<String, String> aliases = new LinkedHashMap<>();
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (!(loader instanceof QuarkusClassLoader)) {
throw new IllegalStateException(QuarkusClassLoader.class.getSimpleName() + " expected as the context class loader");
}
final QuarkusClassLoader quarkusClassLoader = (QuarkusClassLoader) loader;
readConfig(imports, aliases, loader);
final CSimpleCodeGenerator generator = new CSimpleCodeGenerator();
generator.setAliases(aliases);
generator.setImports(imports);
final Path projectDir = Paths.get(".").toAbsolutePath().normalize();
final Path csimpleGeneratedSourceDir = projectDir.resolve("target/generated/csimple");
Files.createDirectories(csimpleGeneratedSourceDir);
final Set<File> filesToCompile = new LinkedHashSet<>();
/* We do not want to compile the same source twice, so we store here what we have compiled already */
final Map<Boolean, Set<String>> compiledExpressions = new HashMap<>();
compiledExpressions.put(true, new HashSet<>());
compiledExpressions.put(false, new HashSet<>());
/* Generate Java classes for the language expressions */
for (CSimpleExpressionSourceBuildItem expr : expressionSources) {
final boolean predicate = expr.isPredicate();
final String script = expr.getSourceCode();
if (!compiledExpressions.get(predicate).contains(script)) {
final CSimpleGeneratedCode code = predicate ? generator.generatePredicate(expr.getClassNameBase(), script) : generator.generateExpression(expr.getClassNameBase(), script);
compiledCSimpleExpression.produce(new CompiledCSimpleExpressionBuildItem(code.getCode(), predicate, code.getFqn()));
final Path javaCsimpleFile = csimpleGeneratedSourceDir.resolve(code.getFqn().replace('.', '/') + ".java");
Files.createDirectories(javaCsimpleFile.getParent());
Files.write(javaCsimpleFile, code.getCode().getBytes(StandardCharsets.UTF_8));
filesToCompile.add(javaCsimpleFile.toFile());
compiledExpressions.get(predicate).add(script);
}
}
final Path csimpleClassesDir = projectDir.resolve("target/csimple-classes");
Files.createDirectories(csimpleClassesDir);
/* Compile the generated sources */
try (JavaCompilationProvider compiler = new JavaCompilationProvider()) {
final Context context = compilationContext(projectDir, csimpleClassesDir, quarkusClassLoader);
compiler.compile(filesToCompile, context);
}
/* Register the compiled classes via Quarkus GeneratedClassBuildItem */
try (Stream<Path> classFiles = Files.walk(csimpleClassesDir)) {
classFiles.filter(Files::isRegularFile).filter(p -> p.getFileName().toString().endsWith(CLASS_EXT)).forEach(p -> {
final Path relPath = csimpleClassesDir.relativize(p);
String className = FileUtils.nixifyPath(relPath.toString());
className = className.substring(0, className.length() - CLASS_EXT.length());
try {
final GeneratedClassBuildItem item = new GeneratedClassBuildItem(true, className, Files.readAllBytes(p));
generatedClasses.produce(item);
} catch (IOException e) {
throw new RuntimeException("Could not read " + p);
}
});
}
}
}
Aggregations