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/04/02 12:25:15 UTC

[camel] 01/02: CAMEL-19173 - Splitting long uris in XML DSLs (#9611)

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 5d8a27a27a4256beae0c6c88abfc84ac4dd4f11c
Author: jacekszymanski <ja...@gmail.com>
AuthorDate: Sun Apr 2 14:16:19 2023 +0200

    CAMEL-19173 - Splitting long uris in XML DSLs (#9611)
    
    * CAMEL-19173: support splitting long URIs in XML IO
    
    * CAMEL-19173: support splitting long URIs in XML JAXB
    
    * CAMEL-19173: XML IO DSL: removing spaces only before parameter names
    
    * CAMEL-19173: XML JAXB DSL: removing spaces only before parameter names
    
    * CAMEL-19173: refactor: code removing noise now in URISupport
---
 .../java/org/apache/camel/util/URISupport.java     | 18 ++++++++++
 .../java/org/apache/camel/xml/in/BaseParser.java   |  4 +++
 .../org/apache/camel/xml/in/ModelParserTest.java   | 41 ++++++++++++++++++++++
 .../java/org/apache/camel/xml/jaxb/JaxbHelper.java | 32 +++++++++++++++++
 4 files changed, 95 insertions(+)

diff --git a/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java b/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java
index ff02e0c330f..3664b88a99b 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/URISupport.java
@@ -808,4 +808,22 @@ public final class URISupport {
         return sb.toString();
     }
 
+    /**
+     * Remove whitespace noise from uri, xxxUri attributes, eg new lines, and tabs etc, which allows end users to format
+     * their Camel routes in more human-readable format, but at runtime those attributes must be trimmed.
+     * The parser removes most of the noise, but keeps spaces in the attribute values
+     */
+    public static String removeNoiseFromUri(String uri) {
+        String before = StringHelper.before(uri, "?");
+        String after = StringHelper.after(uri, "?");
+
+        if (before != null && after != null) {
+            String changed = after.replaceAll("&\\s+", "&").trim();
+            if (!after.equals(changed)) {
+                return before.trim() + "?" + changed;
+            }
+        }
+        return uri;
+    }
+
 }
diff --git a/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/BaseParser.java b/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/BaseParser.java
index 96f892e7a8f..acb837499dc 100644
--- a/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/BaseParser.java
+++ b/core/camel-xml-io/src/main/java/org/apache/camel/xml/in/BaseParser.java
@@ -35,6 +35,7 @@ import org.apache.camel.LineNumberAware;
 import org.apache.camel.model.language.ExpressionDefinition;
 import org.apache.camel.spi.NamespaceAware;
 import org.apache.camel.spi.Resource;
+import org.apache.camel.util.URISupport;
 import org.apache.camel.xml.io.MXParser;
 import org.apache.camel.xml.io.XmlPullParser;
 import org.apache.camel.xml.io.XmlPullParserException;
@@ -105,6 +106,9 @@ public class BaseParser {
             String name = parser.getAttributeName(i);
             String ns = parser.getAttributeNamespace(i);
             String val = parser.getAttributeValue(i);
+            if (name.equals("uri") || name.endsWith("Uri")) {
+                val = URISupport.removeNoiseFromUri(val);
+            }
             if (Objects.equals(ns, "") || Objects.equals(ns, namespace)) {
                 if (attributeHandler == null || !attributeHandler.accept(definition, name, val)) {
                     handleUnexpectedAttribute(namespace, name);
diff --git a/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java b/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java
index c90d0acfd1c..2f9a63b373b 100644
--- a/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java
+++ b/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java
@@ -28,12 +28,14 @@ import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import org.apache.camel.model.FromDefinition;
 import org.apache.camel.model.PropertyDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.RouteTemplatesDefinition;
 import org.apache.camel.model.RoutesDefinition;
 import org.apache.camel.model.SetBodyDefinition;
 import org.apache.camel.model.TemplatedRoutesDefinition;
+import org.apache.camel.model.ToDefinition;
 import org.apache.camel.model.language.XPathExpression;
 import org.apache.camel.model.rest.ParamDefinition;
 import org.apache.camel.model.rest.RestDefinition;
@@ -200,6 +202,45 @@ public class ModelParserTest {
         Assertions.assertEquals(4, param.getAllowableValues().size());
     }
 
+    @Test
+    public void testUriLineBreak() throws Exception {
+        final String fromFrag1 = "seda:a?concurrentConsumers=2&amp;";
+        final String fromFrag2 = "defaultPollTimeout=500";
+        final String jpaFrag1 = "jpa:SomeClass?query=update Object o";
+        final String jpaSpaces = "        ";
+        final String jpaFrag2 = "set o.status = 0";
+        final String toFrag1 = "seda:b?";
+        final String toFrag2 = "lazyStartProducer=true&amp;";
+        final String toFrag3 = "defaultBlockWhenFull=true";
+        final String routesXml = "<routes xmlns=\"" + NAMESPACE + "\">\n"
+                                 + "  <route>\n"
+                                 + "    <from uri=\"" + fromFrag1 + "\n"
+                                 + "        " + fromFrag2 + "\n"
+                                 + "        \"/>\n"
+                                 + "    <to uri=\"" + jpaFrag1 + "\n"
+                                 + jpaSpaces + jpaFrag2 + "\"/>\n"
+                                 + "    <to uri=\"" + toFrag1 + "\n"
+                                 + "        " + toFrag2 + "\n"
+                                 + "        " + toFrag3 + "\"/>\n"
+                                 + "  </route>\n"
+                                 + "</routes>";
+        final RoutesDefinition routes
+                = new ModelParser(new StringReader(routesXml), NAMESPACE).parseRoutesDefinition().orElse(null);
+        final RouteDefinition route = routes.getRoutes().get(0);
+        final FromDefinition from = route.getInput();
+
+        final ToDefinition jpa = (ToDefinition) route.getOutputs().get(0);
+        final ToDefinition to = (ToDefinition) route.getOutputs().get(1);
+
+        final String fromUri = (fromFrag1 + fromFrag2).replace("&amp;", "&");
+        final String jpaUri = jpaFrag1 + " " + jpaSpaces + jpaFrag2; // \n is changed to a single space
+        final String toUri = (toFrag1 + toFrag2 + toFrag3).replace("&amp;", "&");
+
+        Assertions.assertEquals(fromUri, from.getEndpointUri());
+        Assertions.assertEquals(jpaUri, jpa.getEndpointUri());
+        Assertions.assertEquals(toUri, to.getEndpointUri());
+    }
+
     private Path getResourceFolder() {
         String url = getClass().getClassLoader().getResource("barInterceptorRoute.xml").toString();
         if (url.startsWith("file:")) {
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 68c9e7d4be3..d54eb37e9a9 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
@@ -29,10 +29,12 @@ import jakarta.xml.bind.JAXBContext;
 import jakarta.xml.bind.JAXBException;
 import jakarta.xml.bind.Unmarshaller;
 
+import org.w3c.dom.Attr;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Expression;
@@ -59,6 +61,7 @@ import org.apache.camel.model.rest.RestsDefinition;
 import org.apache.camel.spi.NamespaceAware;
 import org.apache.camel.support.PluginHelper;
 import org.apache.camel.util.KeyValueHolder;
+import org.apache.camel.util.URISupport;
 
 import static org.apache.camel.model.ProcessorDefinitionHelper.filterTypeInOutputs;
 
@@ -270,6 +273,7 @@ public final class JaxbHelper {
     public static RoutesDefinition loadRoutesDefinition(CamelContext context, InputStream inputStream) throws Exception {
         XmlConverter xmlConverter = newXmlConverter(context);
         Document dom = xmlConverter.toDOMDocument(inputStream, null);
+        removeNoiseFromUris(dom.getDocumentElement());
 
         JAXBContext jaxbContext = getJAXBContext(context);
 
@@ -310,6 +314,7 @@ public final class JaxbHelper {
             throws Exception {
         XmlConverter xmlConverter = newXmlConverter(context);
         Document dom = xmlConverter.toDOMDocument(inputStream, null);
+        removeNoiseFromUris(dom.getDocumentElement());
 
         JAXBContext jaxbContext = getJAXBContext(context);
 
@@ -350,6 +355,7 @@ public final class JaxbHelper {
             throws Exception {
         XmlConverter xmlConverter = newXmlConverter(context);
         Document dom = xmlConverter.toDOMDocument(inputStream, null);
+        removeNoiseFromUris(dom.getDocumentElement());
 
         JAXBContext jaxbContext = getJAXBContext(context);
 
@@ -398,6 +404,7 @@ public final class JaxbHelper {
             throws Exception {
         XmlConverter xmlConverter = newXmlConverter(context);
         Document dom = xmlConverter.toDOMDocument(inputStream, null);
+        removeNoiseFromUris(dom.getDocumentElement());
 
         JAXBContext jaxbContext = getJAXBContext(context);
 
@@ -448,6 +455,7 @@ public final class JaxbHelper {
     public static RestsDefinition loadRestsDefinition(CamelContext context, InputStream inputStream) throws Exception {
         // load routes using JAXB
         Document dom = newXmlConverter(context).toDOMDocument(inputStream, null);
+        removeNoiseFromUris(dom.getDocumentElement());
 
         if (!CAMEL_NS.equals(dom.getDocumentElement().getNamespaceURI())) {
             addNamespaceToDom(dom);
@@ -474,4 +482,28 @@ public final class JaxbHelper {
 
         return answer;
     }
+
+    private static void removeNoiseFromUris(Element element) {
+        final NamedNodeMap attrs = element.getAttributes();
+
+        for (int index = 0; index < attrs.getLength(); index++) {
+            final Attr attr = (Attr) attrs.item(index);
+            final String attName = attr.getName();
+
+            if (attName.equals("uri") || attName.endsWith("Uri")) {
+                attr.setValue(URISupport.removeNoiseFromUri(attr.getValue()));
+            }
+        }
+
+        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) {
+                removeNoiseFromUris((Element) child);
+            }
+        }
+    }
+
 }