This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch java-dsl-linenumber in repository https://gitbox.apache.org/repos/asf/camel.git
commit e32970b9cfe1dd87d0ca98fd53eb928215772085 Author: Claus Ibsen <[email protected]> AuthorDate: Thu Dec 30 16:53:52 2021 +0100 CAMEL-17400: camel-java-dsl - Add source line number to loaded model. WIP --- .../src/main/docs/camel-csimple-maven-plugin.adoc | 2 +- catalog/camel-java-dsl-maven-plugin/pom.xml | 138 +++++++++++ .../src/main/docs/camel-java-dsl-maven-plugin.adoc | 50 ++++ .../java/org/apache/camel/maven/GenerateMojo.java | 274 +++++++++++++++++++++ .../src/main/resources/META-INF/LICENSE.txt | 203 +++++++++++++++ .../src/main/resources/META-INF/NOTICE.txt | 11 + catalog/pom.xml | 1 + .../java/org/apache/camel/builder/AdviceWith.java | 2 +- .../org/apache/camel/builder/RouteBuilder.java | 6 +- .../apache/camel/model/RouteDefinitionHelper.java | 80 ++++++ .../org/apache/camel/model/RoutesDefinition.java | 5 +- 11 files changed, 766 insertions(+), 6 deletions(-) diff --git a/catalog/camel-csimple-maven-plugin/src/main/docs/camel-csimple-maven-plugin.adoc b/catalog/camel-csimple-maven-plugin/src/main/docs/camel-csimple-maven-plugin.adoc index c609c93..91abf27 100644 --- a/catalog/camel-csimple-maven-plugin/src/main/docs/camel-csimple-maven-plugin.adoc +++ b/catalog/camel-csimple-maven-plugin/src/main/docs/camel-csimple-maven-plugin.adoc @@ -2,7 +2,7 @@ The Camel Compile Simple Maven Plugin supports the following goals - - camel-report:generate - To generate source code for csimple language + - camel-csimple:generate - To generate source code for csimple language == camel:generate diff --git a/catalog/camel-java-dsl-maven-plugin/pom.xml b/catalog/camel-java-dsl-maven-plugin/pom.xml new file mode 100644 index 0000000..4188213 --- /dev/null +++ b/catalog/camel-java-dsl-maven-plugin/pom.xml @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <!-- NOTE parent need to point to camel maven plugins --> + <parent> + <groupId>org.apache.camel</groupId> + <artifactId>maven-plugins</artifactId> + <version>3.15.0-SNAPSHOT</version> + <relativePath>../../tooling/maven</relativePath> + </parent> + + <artifactId>camel-java-dsl-maven-plugin</artifactId> + <packaging>maven-plugin</packaging> + <name>Camel :: Catalog :: Java DSL Maven Plugin</name> + <description>Maven plugin to generate source code line number metadata for Java DSL routes</description> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>tooling-parent</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <dependencies> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-core</artifactId> + </dependency> + <!-- we extend the exec-maven-plugin for this camel maven plugin --> + <dependency> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <exclusions> + <exclusion> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-descriptor</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-api</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-compat</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven.plugin-tools</groupId> + <artifactId>maven-plugin-annotations</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-core</artifactId> + </dependency> + + <!-- disable all components --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-allcomponents</artifactId> + <version>${project.version}</version> + <type>pom</type> + <exclusions> + <exclusion> + <groupId>org.apache.camel</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + + <!-- camel route parser --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-route-parser</artifactId> + <version>${project.version}</version> + </dependency> + + <!-- roaster java parser --> + <dependency> + <groupId>org.jboss.forge.roaster</groupId> + <artifactId>roaster-api</artifactId> + <version>${roaster-version}</version> + </dependency> + <dependency> + <groupId>org.jboss.forge.roaster</groupId> + <artifactId>roaster-jdt</artifactId> + <version>${roaster-version}</version> + </dependency> + + <!-- logging --> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-slf4j-impl</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-plugin-plugin</artifactId> + <configuration> + <mojoDependencies> + <dep>org.codehaus.mojo:exec-maven-plugin</dep> + <dep>org.apache.maven:maven-plugin-api</dep> + </mojoDependencies> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/catalog/camel-java-dsl-maven-plugin/src/main/docs/camel-java-dsl-maven-plugin.adoc b/catalog/camel-java-dsl-maven-plugin/src/main/docs/camel-java-dsl-maven-plugin.adoc new file mode 100644 index 0000000..8382010 --- /dev/null +++ b/catalog/camel-java-dsl-maven-plugin/src/main/docs/camel-java-dsl-maven-plugin.adoc @@ -0,0 +1,50 @@ += Camel Java DSL Maven Plugin + +The Camel Java DSL Maven Plugin supports the following goals + + - camel-java-dsl:generate - To generate source code line number mapping files for Java Routes + +== camel:generate + +To scan source code for Java Routes and generate mapping files, that maps the route EIPs +to their source code line number. This allows Camel to enrich the loaded routes with this +information. + +This can be used by tooling such as debuggers. + +---- +mvn camel-java-dsl:generate +---- + +You should + +[source,xml] +---- +<plugin> + <groupId>org.apache.camel</groupId> + <artifactId>camel-java-dsl-maven-plugin</artifactId> + <executions> + <execution> + <phase>process-classes</phase> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> +</plugin> +---- + +The phase determines when the plugin runs. In the sample above the phase is `process-classes` which runs after +the compilation of the main source code. + +=== Options + +The maven plugin *generate* goal supports the following options which can be configured from the command line (use `-D` syntax), or defined in the `pom.xml` file in the `<configuration>` tag. + +|=== +| Parameter | Default Value | Description +| includeTest | false | Whether to include test source code +| includes | | To filter the names of java files to only include files matching any of the given list of patterns (wildcard and regular expression). Multiple values can be separated by comma. +| excludes | | To filter the names of java files to exclude files matching any of the given list of patterns (wildcard and regular expression). Multiple values can be separated by comma. +|=== + diff --git a/catalog/camel-java-dsl-maven-plugin/src/main/java/org/apache/camel/maven/GenerateMojo.java b/catalog/camel-java-dsl-maven-plugin/src/main/java/org/apache/camel/maven/GenerateMojo.java new file mode 100644 index 0000000..4faa002 --- /dev/null +++ b/catalog/camel-java-dsl-maven-plugin/src/main/java/org/apache/camel/maven/GenerateMojo.java @@ -0,0 +1,274 @@ +/* + * 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.maven; + +import java.io.File; +import java.io.IOError; +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import org.apache.camel.language.csimple.CSimpleCodeGenerator; +import org.apache.camel.parser.RouteBuilderParser; +import org.apache.camel.parser.model.CamelNodeDetails; +import org.apache.camel.support.PatternHelper; +import org.apache.camel.tooling.util.FileUtil; +import org.apache.maven.model.Resource; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; +import org.codehaus.mojo.exec.AbstractExecMojo; +import org.jboss.forge.roaster.Roaster; +import org.jboss.forge.roaster.model.JavaType; +import org.jboss.forge.roaster.model.source.JavaClassSource; + +/** + * Parses the Java DSL source code and generates metadata with source code line number mapping for EIPs which is needed + * by tooling. + */ +@Mojo(name = "generate", threadSafe = true, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, + defaultPhase = LifecyclePhase.GENERATE_SOURCES) +public class GenerateMojo extends AbstractExecMojo { + + public static final String GENERATED_MSG = "Generated by camel build tools - do NOT edit this file!"; + public static final String RESOURCE_DIR = "META-INF/services/org/apache/camel/java-dsl"; + + /** + * The maven project. + */ + @Parameter(property = "project", required = true, readonly = true) + protected MavenProject project; + + // Output directory + + /** + * The output directory for generated resources files + */ + @Parameter(defaultValue = "${project.basedir}/target/classes/" + RESOURCE_DIR) + protected File outputResourceDir; + + /** + * Whether to include test source code + */ + @Parameter(property = "camel.includeTest", defaultValue = "false") + private boolean includeTest; + + /** + * To filter the names of java files to only include files matching any of the given list of patterns (wildcard and + * regular expression). Multiple values can be separated by comma. + */ + @Parameter(property = "camel.includes") + private String includes; + + /** + * To filter the names of java files to exclude files matching any of the given list of patterns (wildcard and + * regular expression). Multiple values can be separated by comma. + */ + @Parameter(property = "camel.excludes") + private String excludes; + + // CHECKSTYLE:OFF + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + CSimpleCodeGenerator generator = new CSimpleCodeGenerator(); + + doExecuteRoutes(generator); + } + + protected void doExecuteRoutes(CSimpleCodeGenerator generator) { + List<CamelNodeDetails> nodes = new ArrayList<>(); + Set<File> javaFiles = new LinkedHashSet<>(); + int classes = 0; + + // find all java route builder classes + List list = project.getCompileSourceRoots(); + for (Object obj : list) { + String dir = (String) obj; + findJavaFiles(new File(dir), javaFiles); + } + if (includeTest) { + list = project.getTestCompileSourceRoots(); + for (Object obj : list) { + String dir = (String) obj; + findJavaFiles(new File(dir), javaFiles); + } + } + + for (File file : javaFiles) { + if (matchRouteFile(file)) { + try { + // parse the java source code and find Camel RouteBuilder classes + String fqn = file.getPath(); + String baseDir = "."; + JavaType<?> out = Roaster.parse(file); + // we should only parse java classes (not interfaces and enums etc) + if (out instanceof JavaClassSource) { + JavaClassSource clazz = (JavaClassSource) out; + List<CamelNodeDetails> output = RouteBuilderParser.parseRouteBuilderTree(clazz, baseDir, fqn, false); + if (!output.isEmpty()) { + nodes.addAll(output); + classes++; + } + } + } catch (Exception e) { + getLog().warn("Error parsing java file " + file + " code due " + e.getMessage(), e); + } + } + } + + if (!nodes.isEmpty()) { + getLog().info("Discovered " + classes + " Java DSL classes"); + + for (CamelNodeDetails node : nodes) { + String fqn = node.getClassName(); + String tree = node.dump(0); + String text = "# " + GENERATED_MSG + "\n" + tree; + String fileName = fqn + ".dump"; + outputResourceDir.mkdirs(); + boolean saved = updateResource(outputResourceDir.toPath().resolve(fileName), text); + if (saved) { + getLog().info("Generated Java DSL source tree dump file: " + fileName); + } + } + } + + } + + // CHECKSTYLE:ON + + private void findJavaFiles(File dir, Set<File> javaFiles) { + File[] files = dir.isDirectory() ? dir.listFiles() : null; + if (files != null) { + for (File file : files) { + if (file.getName().endsWith(".java")) { + javaFiles.add(file); + } else if (file.isDirectory()) { + findJavaFiles(file, javaFiles); + } + } + } + } + + private boolean matchRouteFile(File file) { + if (excludes == null && includes == null) { + return true; + } + + // exclude take precedence + if (excludes != null) { + for (String exclude : excludes.split(",")) { + exclude = exclude.trim(); + // try both with and without directory in the name + String fqn = stripRootPath(asRelativeFile(file.getAbsolutePath())); + boolean match = PatternHelper.matchPattern(fqn, exclude) || PatternHelper.matchPattern(file.getName(), exclude); + if (match) { + return false; + } + } + } + + // include + if (includes != null) { + for (String include : includes.split(",")) { + include = include.trim(); + // try both with and without directory in the name + String fqn = stripRootPath(asRelativeFile(file.getAbsolutePath())); + boolean match = PatternHelper.matchPattern(fqn, include) || PatternHelper.matchPattern(file.getName(), include); + if (match) { + return true; + } + } + // did not match any includes + return false; + } + + // was not excluded nor failed include so its accepted + return true; + } + + private String asRelativeFile(String name) { + String answer = name; + + String base = project.getBasedir().getAbsolutePath(); + if (name.startsWith(base)) { + answer = name.substring(base.length()); + // skip leading slash for relative path + if (answer.startsWith(File.separator)) { + answer = answer.substring(1); + } + } + return answer; + } + + private String stripRootPath(String name) { + // strip out any leading source / resource directory + + List list = project.getCompileSourceRoots(); + for (Object obj : list) { + String dir = (String) obj; + dir = asRelativeFile(dir); + if (name.startsWith(dir)) { + return name.substring(dir.length() + 1); + } + } + list = project.getTestCompileSourceRoots(); + for (Object obj : list) { + String dir = (String) obj; + dir = asRelativeFile(dir); + if (name.startsWith(dir)) { + return name.substring(dir.length() + 1); + } + } + List resources = project.getResources(); + for (Object obj : resources) { + Resource resource = (Resource) obj; + String dir = asRelativeFile(resource.getDirectory()); + if (name.startsWith(dir)) { + return name.substring(dir.length() + 1); + } + } + resources = project.getTestResources(); + for (Object obj : resources) { + Resource resource = (Resource) obj; + String dir = asRelativeFile(resource.getDirectory()); + if (name.startsWith(dir)) { + return name.substring(dir.length() + 1); + } + } + + return name; + } + + public static boolean updateResource(Path out, String data) { + try { + if (FileUtil.updateFile(out, data)) { + return true; + } + } catch (IOException e) { + throw new IOError(e); + } + return false; + } + +} diff --git a/catalog/camel-java-dsl-maven-plugin/src/main/resources/META-INF/LICENSE.txt b/catalog/camel-java-dsl-maven-plugin/src/main/resources/META-INF/LICENSE.txt new file mode 100644 index 0000000..6b0b127 --- /dev/null +++ b/catalog/camel-java-dsl-maven-plugin/src/main/resources/META-INF/LICENSE.txt @@ -0,0 +1,203 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. + diff --git a/catalog/camel-java-dsl-maven-plugin/src/main/resources/META-INF/NOTICE.txt b/catalog/camel-java-dsl-maven-plugin/src/main/resources/META-INF/NOTICE.txt new file mode 100644 index 0000000..2e215bf --- /dev/null +++ b/catalog/camel-java-dsl-maven-plugin/src/main/resources/META-INF/NOTICE.txt @@ -0,0 +1,11 @@ + ========================================================================= + == NOTICE file corresponding to the section 4 d of == + == the Apache License, Version 2.0, == + == in this case for the Apache Camel distribution. == + ========================================================================= + + This product includes software developed by + The Apache Software Foundation (http://www.apache.org/). + + Please read the different LICENSE files present in the licenses directory of + this distribution. diff --git a/catalog/pom.xml b/catalog/pom.xml index 8bb0e27..a1d45e0 100644 --- a/catalog/pom.xml +++ b/catalog/pom.xml @@ -45,6 +45,7 @@ <!-- tooling that depends on catalog --> <module>camel-route-parser</module> <module>camel-csimple-maven-plugin</module> + <module>camel-java-dsl-maven-plugin</module> <module>camel-report-maven-plugin</module> </modules> diff --git a/core/camel-core-model/src/main/java/org/apache/camel/builder/AdviceWith.java b/core/camel-core-model/src/main/java/org/apache/camel/builder/AdviceWith.java index e85ef70..72a99e8 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/builder/AdviceWith.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/builder/AdviceWith.java @@ -229,7 +229,7 @@ public final class AdviceWith { // must re-prepare the merged route before it can be used merged.markUnprepared(); - routes.prepareRoute(merged); + routes.prepareRoute(merged, builder.getClass()); // add the new merged route model.getRouteDefinitions().add(0, merged); diff --git a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java index f3ae520..d6ee6f0 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/builder/RouteBuilder.java @@ -498,7 +498,7 @@ public abstract class RouteBuilder extends BuilderSupport implements RoutesBuild // ensure routes are prepared before being populated for (RouteDefinition route : routeCollection.getRoutes()) { - routeCollection.prepareRoute(route); + routeCollection.prepareRoute(route, this.getClass()); } populateRoutes(); @@ -523,7 +523,7 @@ public abstract class RouteBuilder extends BuilderSupport implements RoutesBuild // ensure routes are prepared before being populated for (RouteDefinition route : routeCollection.getRoutes()) { - routeCollection.prepareRoute(route); + routeCollection.prepareRoute(route, this.getClass()); } // trigger update of the routes @@ -611,7 +611,7 @@ public abstract class RouteBuilder extends BuilderSupport implements RoutesBuild for (RouteDefinition route : getRouteCollection().getRoutes()) { // ensure the route is prepared after configure method is complete - getRouteCollection().prepareRoute(route); + getRouteCollection().prepareRoute(route, this.getClass()); } for (RouteBuilderLifecycleStrategy interceptor : lifecycleInterceptors) { diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java index c61d997..cca3a7a 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java @@ -16,12 +16,16 @@ */ package org.apache.camel.model; +import java.io.IOException; +import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -34,9 +38,13 @@ import org.apache.camel.RuntimeCamelException; import org.apache.camel.builder.ErrorHandlerBuilder; import org.apache.camel.model.rest.RestDefinition; import org.apache.camel.model.rest.VerbDefinition; +import org.apache.camel.spi.Resource; import org.apache.camel.support.CamelContextHelper; import org.apache.camel.support.EndpointHelper; +import org.apache.camel.support.ResourceSupport; +import org.apache.camel.util.IOHelper; import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.StringHelper; import org.apache.camel.util.URISupport; import static org.apache.camel.model.ProcessorDefinitionHelper.filterTypeInOutputs; @@ -757,4 +765,76 @@ public final class RouteDefinitionHelper { return route; } } + + public static void prepareJavaDslRoute(CamelContext camelContext, RouteDefinition route, Class<?> builder) { + String fqn = builder != null ? builder.getName() : null; + if (fqn != null) { + String name = "META-INF/services/org/apache/camel/java-dsl/" + fqn + ".dump"; + InputStream is = camelContext.adapt(ExtendedCamelContext.class).getClassResolver().loadResourceAsStream(name); + if (is != null) { + try { + String lines = IOHelper.loadText(is); + Iterator<String> it = Arrays.stream(lines.split("\n")).iterator(); + // skip first two lines + it.next(); + String first = it.next(); + + if (route.getInput().getLineNumber() < 0) { + String digit = StringHelper.before(first, "\t"); + if (digit != null) { + int num = Integer.parseInt(digit); + route.getInput().setLineNumber(num); + } + } + if (route.getResource() == null) { + // build a pseudo resource (TODO: make as inner class) + Resource res = new ResourceSupport("class", builder.getName()) { + @Override + public boolean exists() { + return false; + } + + @Override + public InputStream getInputStream() throws IOException { + return null; + } + }; + route.setResource(res); + } + + Iterator<ProcessorDefinition> col = ProcessorDefinitionHelper + .filterTypeInOutputs(route.getOutputs(), ProcessorDefinition.class).iterator(); + + while (it.hasNext() && col.hasNext()) { + String line = it.next(); + ProcessorDefinition<?> def = col.next(); + + if (def instanceof WhenDefinition || def instanceof OtherwiseDefinition) { + // skip these as they are not in the dump + def = col.next(); + } + if (def != null) { + int num = def.getLineNumber(); + if (num < 0) { + // parse line + String digit = StringHelper.before(line, "\t"); + if (digit != null) { + try { + num = Integer.parseInt(digit); + def.setLineNumber(num); + } catch (Exception e) { + // ignore + } + } + } + } + } + } catch (Exception e) { + // ignore + } finally { + IOHelper.close(is); + } + } + } + } } diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java index fce66a6..1d7c873 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RoutesDefinition.java @@ -225,7 +225,7 @@ public class RoutesDefinition extends OptionalIdentifiedDefinition<RoutesDefinit return route; } - public void prepareRoute(RouteDefinition route) { + public void prepareRoute(RouteDefinition route, Class<?> builder) { if (route.isPrepared()) { return; } @@ -278,6 +278,9 @@ public class RoutesDefinition extends OptionalIdentifiedDefinition<RoutesDefinit // must prepare the route before we can add it to the routes list RouteDefinitionHelper.prepareRoute(getCamelContext(), route, oe, icp, ifrom, ito, oc); + // enrich the route with line number details if we have metadata when using Java compiled routes + RouteDefinitionHelper.prepareJavaDslRoute(camelContext, route, builder); + if (LOG.isDebugEnabled() && route.getAppliedRouteConfigurationIds() != null) { LOG.debug("Route: {} is using route configurations ids: {}", route.getId(), route.getAppliedRouteConfigurationIds());
