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 2023/11/23 12:56:32 UTC

(camel) 01/01: CAMEL-20143: camel-core - Dump route when debugger enable should include source line

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch debug-source-line
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 465a81b56735394938a598839567b29422745644
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Nov 23 13:56:16 2023 +0100

    CAMEL-20143: camel-core - Dump route when debugger enable should include source line
---
 .../management/mbean/ManagedCamelContext.java      |   9 ++
 .../camel/management/mbean/ManagedRoute.java       |   4 +
 .../java/org/apache/camel/xml/jaxb/JaxbHelper.java | 108 ++++++++++++++++++++-
 .../camel/xml/jaxb/JaxbModelToXMLDumper.java       |  36 +------
 4 files changed, 123 insertions(+), 34 deletions(-)

diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java
index b709ad93c29..519eb33313a 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java
@@ -488,6 +488,10 @@ public class ManagedCamelContext extends ManagedPerformanceCounter implements Ti
         RoutesDefinition def = new RoutesDefinition();
         def.setRoutes(routes);
 
+        // if we are debugging then ids is needed for the debugger
+        if (context.isDebugging()) {
+            generatedIds = true;
+        }
         return PluginHelper.getModelToXMLDumper(context).dumpModelAsXml(context, def, resolvePlaceholders, generatedIds);
     }
 
@@ -518,6 +522,11 @@ public class ManagedCamelContext extends ManagedPerformanceCounter implements Ti
         RoutesDefinition def = new RoutesDefinition();
         def.setRoutes(routes);
 
+        // if we are debugging then ids is needed for the debugger
+        if (context.isDebugging()) {
+            generatedIds = true;
+        }
+
         return PluginHelper.getModelToYAMLDumper(context).dumpModelAsYaml(context, def, resolvePlaceholders, uriAsParameters,
                 generatedIds);
     }
diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java
index 0f7e00790e1..301739c0df4 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java
@@ -396,6 +396,10 @@ public class ManagedRoute extends ManagedPerformanceCounter implements TimerList
         String id = route.getId();
         RouteDefinition def = context.getCamelContextExtension().getContextPlugin(Model.class).getRouteDefinition(id);
         if (def != null) {
+            // if we are debugging then ids is needed for the debugger
+            if (context.isDebugging()) {
+                generatedIds = true;
+            }
             return PluginHelper.getModelToXMLDumper(context).dumpModelAsXml(context, def, resolvePlaceholders, generatedIds);
         }
 
diff --git a/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbHelper.java b/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbHelper.java
index 07d77c7a422..41099653e46 100644
--- a/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbHelper.java
+++ b/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbHelper.java
@@ -20,6 +20,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -195,6 +196,41 @@ public final class JaxbHelper {
         }
     }
 
+    /**
+     * Extract all source locations from the XML routes
+     *
+     * @param element   the XML element
+     * @param locations the map of source locations for EIPs in the route
+     */
+    public static void extractSourceLocations(Element element, Map<String, KeyValueHolder<Integer, String>> locations) {
+        NamedNodeMap attributes = element.getAttributes();
+        String id = null;
+        Integer sourceLineNumber = null;
+        String sourceLocation = null;
+        for (int i = 0; i < attributes.getLength(); i++) {
+            Node item = attributes.item(i);
+            String name = item.getNodeName();
+            if ("id".equals(name)) {
+                id = item.getNodeValue();
+            } else if ("sourceLineNumber".equals(name)) {
+                sourceLineNumber = Integer.parseInt(item.getNodeValue());
+            } else if ("sourceLocation".equals(name)) {
+                sourceLocation = item.getNodeValue();
+            }
+        }
+        if (id != null && sourceLineNumber != null && sourceLocation != null) {
+            locations.put(id, new KeyValueHolder<>(sourceLineNumber, sourceLocation));
+        }
+
+        final NodeList children = element.getChildNodes();
+        for (int index = 0; index < children.getLength(); index++) {
+            final Node child = children.item(index);
+            if (child.getNodeType() == Node.ELEMENT_NODE) {
+                extractSourceLocations((Element) child, locations);
+            }
+        }
+    }
+
     public static void applyNamespaces(RouteDefinition route, Map<String, String> namespaces) {
         Collection<ExpressionNode> col = filterTypeInOutputs(route.getOutputs(), ExpressionNode.class);
         for (ExpressionNode en : col) {
@@ -223,6 +259,24 @@ public final class JaxbHelper {
         }
     }
 
+    public static void applySourceLocations(RouteDefinition route, Map<String, KeyValueHolder<Integer, String>> locations) {
+        KeyValueHolder<Integer, String> kv = locations.get(route.getRouteId());
+        if (kv != null && route.getInput() != null) {
+            route.getInput().setLineNumber(kv.getKey());
+            route.getInput().setLocation(kv.getValue());
+        }
+
+        Collection<OptionalIdentifiedDefinition> def
+                = filterTypeInOutputs(route.getOutputs(), OptionalIdentifiedDefinition.class);
+        for (OptionalIdentifiedDefinition out : def) {
+            kv = locations.get(out.getId());
+            if (kv != null) {
+                out.setLineNumber(kv.getKey());
+                out.setLocation(kv.getValue());
+            }
+        }
+    }
+
     public static <T extends NamedNode> T modelToXml(CamelContext context, String xml, Class<T> type) throws Exception {
         JAXBContext jaxbContext = getJAXBContext(context);
 
@@ -237,6 +291,10 @@ public final class JaxbHelper {
             throw new IllegalArgumentException("InputStream and XML is both null");
         }
 
+        Map<String, KeyValueHolder<Integer, String>> locations = new HashMap<>();
+        if (context.isDebugging()) {
+            extractSourceLocations(dom.getDocumentElement(), locations);
+        }
         Map<String, String> namespaces = new LinkedHashMap<>();
         extractNamespaces(dom, namespaces);
 
@@ -251,19 +309,37 @@ public final class JaxbHelper {
         if (result instanceof RouteTemplatesDefinition) {
             List<RouteTemplateDefinition> templates = ((RouteTemplatesDefinition) result).getRouteTemplates();
             for (RouteTemplateDefinition template : templates) {
-                applyNamespaces(template.getRoute(), namespaces);
+                RouteDefinition route = template.getRoute();
+                applyNamespaces(route, namespaces);
+                if (!locations.isEmpty()) {
+                    applySourceLocations(route, locations);
+                }
+                resolveEndpointDslUris(route);
             }
         } else if (result instanceof RouteTemplateDefinition) {
             RouteTemplateDefinition template = (RouteTemplateDefinition) result;
-            applyNamespaces(template.getRoute(), namespaces);
+            RouteDefinition route = template.getRoute();
+            applyNamespaces(route, namespaces);
+            if (!locations.isEmpty()) {
+                applySourceLocations(route, locations);
+            }
+            resolveEndpointDslUris(route);
         } else if (result instanceof RoutesDefinition) {
             List<RouteDefinition> routes = ((RoutesDefinition) result).getRoutes();
             for (RouteDefinition route : routes) {
                 applyNamespaces(route, namespaces);
+                if (!locations.isEmpty()) {
+                    applySourceLocations(route, locations);
+                }
+                resolveEndpointDslUris(route);
             }
         } else if (result instanceof RouteDefinition) {
             RouteDefinition route = (RouteDefinition) result;
             applyNamespaces(route, namespaces);
+            if (!locations.isEmpty()) {
+                applySourceLocations(route, locations);
+            }
+            resolveEndpointDslUris(route);
         }
 
         return type.cast(result);
@@ -530,4 +606,32 @@ public final class JaxbHelper {
         }
     }
 
+    public static void enrichLocations(Node node, Map<String, KeyValueHolder<Integer, String>> locations) {
+        if (node instanceof Element) {
+            Element el = (Element) node;
+
+            // from should grab it from parent (route)
+            String id = el.getAttribute("id");
+            if ("from".equals(el.getNodeName())) {
+                Node parent = el.getParentNode();
+                if (parent instanceof Element) {
+                    id = ((Element) parent).getAttribute("id");
+                }
+            }
+            if (id != null) {
+                var loc = locations.get(id);
+                if (loc != null) {
+                    el.setAttribute("sourceLineNumber", loc.getKey().toString());
+                    el.setAttribute("sourceLocation", loc.getValue());
+                }
+            }
+        }
+        if (node.hasChildNodes()) {
+            for (int i = 0; i < node.getChildNodes().getLength(); i++) {
+                Node child = node.getChildNodes().item(i);
+                enrichLocations(child, locations);
+            }
+        }
+    }
+
 }
diff --git a/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbModelToXMLDumper.java b/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbModelToXMLDumper.java
index 1c6c67f124b..9a0c4440553 100644
--- a/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbModelToXMLDumper.java
+++ b/core/camel-xml-jaxb/src/main/java/org/apache/camel/xml/jaxb/JaxbModelToXMLDumper.java
@@ -58,12 +58,12 @@ import org.apache.camel.support.PluginHelper;
 import org.apache.camel.util.KeyValueHolder;
 import org.apache.camel.util.xml.XmlLineNumberParser;
 
+import static org.apache.camel.xml.jaxb.JaxbHelper.enrichLocations;
 import static org.apache.camel.xml.jaxb.JaxbHelper.extractNamespaces;
 import static org.apache.camel.xml.jaxb.JaxbHelper.extractSourceLocations;
 import static org.apache.camel.xml.jaxb.JaxbHelper.getJAXBContext;
 import static org.apache.camel.xml.jaxb.JaxbHelper.modelToXml;
 import static org.apache.camel.xml.jaxb.JaxbHelper.newXmlConverter;
-import static org.apache.camel.xml.jaxb.JaxbHelper.removeAutoAssignedIds;
 import static org.apache.camel.xml.jaxb.JaxbHelper.resolveEndpointDslUris;
 
 /**
@@ -201,8 +201,9 @@ public class JaxbModelToXMLDumper implements ModelToXMLDumper {
                         pc.setLocalProperties(null);
                     }
 
-                    if (!changed.get()) {
-                        changed.set(!text.equals(after));
+                    boolean updated = !text.equals(after);
+                    if (updated && !changed.get()) {
+                        changed.set(true);
                     }
 
                     return after;
@@ -212,7 +213,6 @@ public class JaxbModelToXMLDumper implements ModelToXMLDumper {
             // okay there were some property placeholder or delegate endpoints
             // replaced so re-create the model
             if (changed.get()) {
-                removeAutoAssignedIds(dom.getDocumentElement());
                 xml = context.getTypeConverter().mandatoryConvertTo(String.class, dom);
                 NamedNode copy = modelToXml(context, xml, NamedNode.class);
                 xml = PluginHelper.getModelToXMLDumper(context).dumpModelAsXml(context, copy, false, generatedIds);
@@ -268,34 +268,6 @@ public class JaxbModelToXMLDumper implements ModelToXMLDumper {
         }
     }
 
-    private static void enrichLocations(Node node, Map<String, KeyValueHolder<Integer, String>> locations) {
-        if (node instanceof Element) {
-            Element el = (Element) node;
-
-            // from should grab it from parent (route)
-            String id = el.getAttribute("id");
-            if ("from".equals(el.getNodeName())) {
-                Node parent = el.getParentNode();
-                if (parent instanceof Element) {
-                    id = ((Element) parent).getAttribute("id");
-                }
-            }
-            if (id != null) {
-                var loc = locations.get(id);
-                if (loc != null) {
-                    el.setAttribute("sourceLineNumber", loc.getKey().toString());
-                    el.setAttribute("sourceLocation", loc.getValue());
-                }
-            }
-        }
-        if (node.hasChildNodes()) {
-            for (int i = 0; i < node.getChildNodes().getLength(); i++) {
-                Node child = node.getChildNodes().item(i);
-                enrichLocations(child, locations);
-            }
-        }
-    }
-
     private static class BeanModelWriter implements CamelContextAware {
 
         private final StringWriter buffer;