Repository: camel
Updated Branches:
  refs/heads/camel-2.16.x 2264701f7 -> 7c2905f40
  refs/heads/master 21bbdaa5a -> e253b5b28


CAMEL-9687: Dump route/rests from JMX now support resolving property 
placeholders. Needed in camel-swagger-java so the rest api is presented with 
resolved values.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/84640611
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/84640611
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/84640611

Branch: refs/heads/master
Commit: 8464061167525be94fd457e57caabd5165d520a0
Parents: 21bbdaa
Author: Claus Ibsen <davscl...@apache.org>
Authored: Wed Mar 9 21:02:57 2016 +0100
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Wed Mar 9 21:02:57 2016 +0100

----------------------------------------------------------------------
 .../mbean/ManagedCamelContextMBean.java         |   6 +
 .../api/management/mbean/ManagedRouteMBean.java |   3 +
 .../management/mbean/ManagedCamelContext.java   |  73 ++++++-
 .../camel/management/mbean/ManagedRoute.java    |  40 +++-
 .../camel/model/RouteDefinitionHelper.java      |   1 -
 .../apache/camel/util/XmlLineNumberParser.java  | 192 +++++++++++++++++++
 .../ManagedFromRestPlaceholderTest.java         | 119 ++++++++++++
 ...nagedRouteDumpRouteAsXmlPlaceholderTest.java |  96 ++++++++++
 .../org/apache/camel/management/rest.properties |  22 +++
 .../camel/swagger/RestSwaggerSupport.java       |  11 +-
 ...estSwaggerReaderPropertyPlaceholderTest.java | 108 +++++++++++
 11 files changed, 665 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/84640611/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java
 
b/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java
index 4cb8905..d71472e 100644
--- 
a/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java
+++ 
b/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java
@@ -178,9 +178,15 @@ public interface ManagedCamelContextMBean extends 
ManagedPerformanceCounterMBean
     @ManagedOperation(description = "Dumps the rests as XML")
     String dumpRestsAsXml() throws Exception;
 
+    @ManagedOperation(description = "Dumps the rests as XML")
+    String dumpRestsAsXml(boolean resolvePlaceholders) throws Exception;
+
     @ManagedOperation(description = "Dumps the routes as XML")
     String dumpRoutesAsXml() throws Exception;
 
+    @ManagedOperation(description = "Dumps the routes as XML")
+    String dumpRoutesAsXml(boolean resolvePlaceholders) throws Exception;
+
     @ManagedOperation(description = "Adds or updates existing routes from XML")
     void addOrUpdateRoutesFromXml(String xml) throws Exception;
 

http://git-wip-us.apache.org/repos/asf/camel/blob/84640611/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java
 
b/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java
index 9d9e9b8..bdc26f7 100644
--- 
a/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java
+++ 
b/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java
@@ -102,6 +102,9 @@ public interface ManagedRouteMBean extends 
ManagedPerformanceCounterMBean {
     @ManagedOperation(description = "Dumps the route as XML")
     String dumpRouteAsXml() throws Exception;
 
+    @ManagedOperation(description = "Dumps the route as XML")
+    String dumpRouteAsXml(boolean resolvePlaceholders) throws Exception;
+
     @ManagedOperation(description = "Updates the route from XML")
     void updateRouteFromXml(String xml) throws Exception;
 

http://git-wip-us.apache.org/repos/asf/camel/blob/84640611/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java
 
b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java
index a694bb8..8eb77d5 100644
--- 
a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java
+++ 
b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java
@@ -29,6 +29,7 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 import javax.management.MBeanServer;
 import javax.management.ObjectName;
 import javax.management.openmbean.CompositeData;
@@ -63,7 +64,7 @@ import org.apache.camel.spi.ManagementStrategy;
 import org.apache.camel.util.CamelContextHelper;
 import org.apache.camel.util.JsonSchemaHelper;
 import org.apache.camel.util.ObjectHelper;
-
+import org.apache.camel.util.XmlLineNumberParser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -348,6 +349,11 @@ public class ManagedCamelContext extends 
ManagedPerformanceCounter implements Ti
     }
 
     public String dumpRestsAsXml() throws Exception {
+        return dumpRestsAsXml(false);
+    }
+
+    @Override
+    public String dumpRestsAsXml(boolean resolvePlaceholders) throws Exception 
{
         List<RestDefinition> rests = context.getRestDefinitions();
         if (rests.isEmpty()) {
             return null;
@@ -356,10 +362,43 @@ public class ManagedCamelContext extends 
ManagedPerformanceCounter implements Ti
         // use a routes definition to dump the rests
         RestsDefinition def = new RestsDefinition();
         def.setRests(rests);
-        return ModelHelper.dumpModelAsXml(context, def);
+        String xml = ModelHelper.dumpModelAsXml(context, def);
+
+        if (resolvePlaceholders) {
+            final AtomicBoolean changed = new AtomicBoolean();
+            InputStream is = new ByteArrayInputStream(xml.getBytes());
+            Document dom = XmlLineNumberParser.parseXml(is, new 
XmlLineNumberParser.XmlTextTransformer() {
+                @Override
+                public String transform(String text) {
+                    try {
+                        String after = 
getContext().resolvePropertyPlaceholders(text);
+                        if (!changed.get()) {
+                            changed.set(!text.equals(after));
+                        }
+                        return after;
+                    } catch (Exception e) {
+                        // ignore
+                        return text;
+                    }
+                }
+            });
+            // okay there were some property placeholder replaced so re-create 
the model
+            if (changed.get()) {
+                xml = 
context.getTypeConverter().mandatoryConvertTo(String.class, dom);
+                RestsDefinition copy = ModelHelper.createModelFromXml(context, 
xml, RestsDefinition.class);
+                xml = ModelHelper.dumpModelAsXml(context, copy);
+            }
+        }
+
+        return xml;
     }
 
     public String dumpRoutesAsXml() throws Exception {
+        return dumpRoutesAsXml(false);
+    }
+
+    @Override
+    public String dumpRoutesAsXml(boolean resolvePlaceholders) throws 
Exception {
         List<RouteDefinition> routes = context.getRouteDefinitions();
         if (routes.isEmpty()) {
             return null;
@@ -368,7 +407,35 @@ public class ManagedCamelContext extends 
ManagedPerformanceCounter implements Ti
         // use a routes definition to dump the routes
         RoutesDefinition def = new RoutesDefinition();
         def.setRoutes(routes);
-        return ModelHelper.dumpModelAsXml(context, def);
+        String xml = ModelHelper.dumpModelAsXml(context, def);
+
+        if (resolvePlaceholders) {
+            final AtomicBoolean changed = new AtomicBoolean();
+            InputStream is = new ByteArrayInputStream(xml.getBytes());
+            Document dom = XmlLineNumberParser.parseXml(is, new 
XmlLineNumberParser.XmlTextTransformer() {
+                @Override
+                public String transform(String text) {
+                    try {
+                        String after = 
getContext().resolvePropertyPlaceholders(text);
+                        if (!changed.get()) {
+                            changed.set(!text.equals(after));
+                        }
+                        return after;
+                    } catch (Exception e) {
+                        // ignore
+                        return text;
+                    }
+                }
+            });
+            // okay there were some property placeholder replaced so re-create 
the model
+            if (changed.get()) {
+                xml = 
context.getTypeConverter().mandatoryConvertTo(String.class, dom);
+                RoutesDefinition copy = 
ModelHelper.createModelFromXml(context, xml, RoutesDefinition.class);
+                xml = ModelHelper.dumpModelAsXml(context, copy);
+            }
+        }
+
+        return xml;
     }
 
     public void addOrUpdateRoutesFromXml(String xml) throws Exception {

http://git-wip-us.apache.org/repos/asf/camel/blob/84640611/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java 
b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java
index 47760f3..837d798 100644
--- 
a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java
+++ 
b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java
@@ -16,6 +16,8 @@
  */
 package org.apache.camel.management.mbean;
 
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -26,6 +28,7 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentSkipListMap;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 import javax.management.AttributeValueExp;
 import javax.management.MBeanServer;
 import javax.management.ObjectName;
@@ -33,6 +36,8 @@ import javax.management.Query;
 import javax.management.QueryExp;
 import javax.management.StringValueExp;
 
+import org.w3c.dom.Document;
+
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.ManagementStatisticsLevel;
@@ -48,6 +53,7 @@ import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.spi.ManagementStrategy;
 import org.apache.camel.spi.RoutePolicy;
 import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.XmlLineNumberParser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -256,10 +262,42 @@ public class ManagedRoute extends 
ManagedPerformanceCounter implements TimerList
     }
 
     public String dumpRouteAsXml() throws Exception {
+        return dumpRouteAsXml(false);
+    }
+
+    @Override
+    public String dumpRouteAsXml(boolean resolvePlaceholders) throws Exception 
{
         String id = route.getId();
         RouteDefinition def = context.getRouteDefinition(id);
         if (def != null) {
-            return ModelHelper.dumpModelAsXml(context, def);
+            String xml = ModelHelper.dumpModelAsXml(context, def);
+
+            if (resolvePlaceholders) {
+                final AtomicBoolean changed = new AtomicBoolean();
+                InputStream is = new ByteArrayInputStream(xml.getBytes());
+                Document dom = XmlLineNumberParser.parseXml(is, new 
XmlLineNumberParser.XmlTextTransformer() {
+                    @Override
+                    public String transform(String text) {
+                        try {
+                            String after = 
getContext().resolvePropertyPlaceholders(text);
+                            if (!changed.get()) {
+                                changed.set(!text.equals(after));
+                            }
+                            return after;
+                        } catch (Exception e) {
+                            // ignore
+                            return text;
+                        }
+                    }
+                });
+                // okay there were some property placeholder replaced so 
re-create the model
+                if (changed.get()) {
+                    xml = 
context.getTypeConverter().mandatoryConvertTo(String.class, dom);
+                    RouteDefinition copy = 
ModelHelper.createModelFromXml(context, xml, RouteDefinition.class);
+                    xml = ModelHelper.dumpModelAsXml(context, copy);
+                }
+            }
+            return xml;
         }
         return null;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/84640611/camel-core/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java 
b/camel-core/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java
index 42d2825..fccc918 100644
--- a/camel-core/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java
+++ b/camel-core/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java
@@ -382,7 +382,6 @@ public final class RouteDefinitionHelper {
         }
     }
 
-
     private static void initParentAndErrorHandlerBuilder(ModelCamelContext 
context, RouteDefinition route,
                                                          
List<ProcessorDefinition<?>> abstracts, List<OnExceptionDefinition> 
onExceptions) {
 

http://git-wip-us.apache.org/repos/asf/camel/blob/84640611/camel-core/src/main/java/org/apache/camel/util/XmlLineNumberParser.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/util/XmlLineNumberParser.java 
b/camel-core/src/main/java/org/apache/camel/util/XmlLineNumberParser.java
new file mode 100644
index 0000000..2eb1a28
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/util/XmlLineNumberParser.java
@@ -0,0 +1,192 @@
+/**
+ * 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.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.util.Stack;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * An XML parser that uses SAX to include line and column number for each XML 
element in the parsed Document.
+ * <p>
+ * The line number and column number can be obtained from a Node/Element using
+ * <pre>
+ *   String lineNumber = (String) 
node.getUserData(XmlLineNumberParser.LINE_NUMBER);
+ *   String lineNumberEnd = (String) 
node.getUserData(XmlLineNumberParser.LINE_NUMBER_END);
+ *   String columnNumber = (String) 
node.getUserData(XmlLineNumberParser.COLUMN_NUMBER);
+ *   String columnNumberEnd = (String) 
node.getUserData(XmlLineNumberParser.COLUMN_NUMBER_END);
+ * </pre>
+ */
+public final class XmlLineNumberParser {
+
+    public static final String LINE_NUMBER = "lineNumber";
+    public static final String COLUMN_NUMBER = "colNumber";
+    public static final String LINE_NUMBER_END = "lineNumberEnd";
+    public static final String COLUMN_NUMBER_END = "colNumberEnd";
+
+    /**
+     * Allows to plugin a custom text transformer in the parser, that can 
transform all the text content
+     */
+    public interface XmlTextTransformer {
+
+        String transform(String text);
+
+    }
+
+    private XmlLineNumberParser() {
+    }
+
+    /**
+     * Parses the XML.
+     *
+     * @param is the XML content as an input stream
+     * @return the DOM model
+     * @throws Exception is thrown if error parsing
+     */
+    public static Document parseXml(final InputStream is) throws Exception {
+        return parseXml(is, new NoopTransformer());
+    }
+
+    /**
+     * Parses the XML.
+     *
+     * @param is the XML content as an input stream
+     * @return the DOM model
+     * @throws Exception is thrown if error parsing
+     */
+    public static Document parseXml(final InputStream is, final 
XmlTextTransformer transformer) throws Exception {
+        ObjectHelper.notNull(is, "is");
+        ObjectHelper.notNull(transformer, "transformer");
+
+        final Document doc;
+        SAXParser parser;
+        final SAXParserFactory factory = SAXParserFactory.newInstance();
+        parser = factory.newSAXParser();
+        final DocumentBuilderFactory dbf = 
DocumentBuilderFactory.newInstance();
+        // turn off validator and loading external dtd
+        dbf.setValidating(false);
+        dbf.setNamespaceAware(true);
+        dbf.setFeature("http://xml.org/sax/features/namespaces";, false);
+        dbf.setFeature("http://xml.org/sax/features/validation";, false);
+        
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar";, 
false);
+        
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd";,
 false);
+        
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities";, 
false);
+        
dbf.setFeature("http://xml.org/sax/features/external-general-entities";, false);
+        final DocumentBuilder docBuilder = dbf.newDocumentBuilder();
+        doc = docBuilder.newDocument();
+
+        final Stack<Element> elementStack = new Stack<Element>();
+        final StringBuilder textBuffer = new StringBuilder();
+        final DefaultHandler handler = new DefaultHandler() {
+            private Locator locator;
+            private boolean found;
+
+            @Override
+            public void setDocumentLocator(final Locator locator) {
+                this.locator = locator; // Save the locator, so that it can be 
used later for line tracking when traversing nodes.
+            }
+
+            @Override
+            public void startElement(final String uri, final String localName, 
final String qName, final Attributes attributes) throws SAXException {
+                addTextIfNeeded();
+
+                Element el = doc.createElement(qName);
+
+                for (int i = 0; i < attributes.getLength(); i++) {
+                    
el.setAttribute(transformer.transform(attributes.getQName(i)), 
transformer.transform(attributes.getValue(i)));
+                }
+
+                el.setUserData(LINE_NUMBER, 
String.valueOf(this.locator.getLineNumber()), null);
+                el.setUserData(COLUMN_NUMBER, 
String.valueOf(this.locator.getColumnNumber()), null);
+                elementStack.push(el);
+            }
+
+            @Override
+            public void endElement(final String uri, final String localName, 
final String qName) {
+                addTextIfNeeded();
+
+                final Element closedEl = elementStack.isEmpty() ? null : 
elementStack.pop();
+                if (closedEl != null) {
+                    if (elementStack.isEmpty()) {
+                        // Is this the root element?
+                        doc.appendChild(closedEl);
+                    } else {
+                        final Element parentEl = elementStack.peek();
+                        parentEl.appendChild(closedEl);
+                    }
+
+                    closedEl.setUserData(LINE_NUMBER_END, 
String.valueOf(this.locator.getLineNumber()), null);
+                    closedEl.setUserData(COLUMN_NUMBER_END, 
String.valueOf(this.locator.getColumnNumber()), null);
+                }
+            }
+
+            @Override
+            public void characters(final char ch[], final int start, final int 
length) throws SAXException {
+                char[] chars = new char[length];
+                System.arraycopy(ch, start, chars, 0, length);
+                String s = new String(chars);
+                s = transformer.transform(s);
+                textBuffer.append(s);
+            }
+
+            @Override
+            public InputSource resolveEntity(String publicId, String systemId) 
throws IOException, SAXException {
+                // do not resolve external dtd
+                return new InputSource(new StringReader(""));
+            }
+
+            // Outputs text accumulated under the current node
+            private void addTextIfNeeded() {
+                if (textBuffer.length() > 0) {
+                    final Element el = elementStack.isEmpty() ? null : 
elementStack.peek();
+                    if (el != null) {
+                        final Node textNode = 
doc.createTextNode(textBuffer.toString());
+                        el.appendChild(textNode);
+                        textBuffer.delete(0, textBuffer.length());
+                    }
+                }
+            }
+        };
+        parser.parse(is, handler);
+
+        return doc;
+    }
+
+    private static final class NoopTransformer implements XmlTextTransformer {
+
+        @Override
+        public String transform(String text) {
+            return text;
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/84640611/camel-core/src/test/java/org/apache/camel/management/ManagedFromRestPlaceholderTest.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/test/java/org/apache/camel/management/ManagedFromRestPlaceholderTest.java
 
b/camel-core/src/test/java/org/apache/camel/management/ManagedFromRestPlaceholderTest.java
new file mode 100644
index 0000000..40d4057
--- /dev/null
+++ 
b/camel-core/src/test/java/org/apache/camel/management/ManagedFromRestPlaceholderTest.java
@@ -0,0 +1,119 @@
+/**
+ * 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.management;
+
+import java.util.Arrays;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.properties.PropertiesComponent;
+import org.apache.camel.component.rest.DummyRestConsumerFactory;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.SimpleRegistry;
+import org.apache.camel.model.rest.CollectionFormat;
+import org.apache.camel.model.rest.RestParamType;
+
+public class ManagedFromRestPlaceholderTest extends ManagementTestSupport {
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        SimpleRegistry registry = new SimpleRegistry();
+        registry.put("dummy-test", new DummyRestConsumerFactory());
+
+        CamelContext answer = new DefaultCamelContext(registry);
+
+        PropertiesComponent pc = new PropertiesComponent();
+        
pc.setLocation("classpath:org/apache/camel/management/rest.properties");
+        answer.addComponent("properties", pc);
+
+        return answer;
+    }
+
+    public void testFromRestModelPlaceholder() throws Exception {
+        // JMX tests dont work well on AIX CI servers (hangs them)
+        if (isPlatform("aix")) {
+            return;
+        }
+
+        MBeanServer mbeanServer = getMBeanServer();
+
+        ObjectName on = 
ObjectName.getInstance("org.apache.camel:context=camel-1,type=context,name=\"camel-1\"");
+
+        String xml = (String) mbeanServer.invoke(on, "dumpRestsAsXml", new 
Object[]{true}, new String[]{"boolean"});
+        assertNotNull(xml);
+        log.info(xml);
+
+        assertTrue(xml.contains("<rests"));
+        assertTrue(xml.contains("<rest path=\"/say/hello\">"));
+        assertTrue(xml.contains("<rest path=\"/say/bye\">"));
+        assertTrue(xml.contains("</rest>"));
+        assertTrue(xml.contains("<get"));
+        assertTrue(xml.contains("application/json"));
+        assertTrue(xml.contains("<post"));
+        assertTrue(xml.contains("application/json"));
+        assertTrue(xml.contains("</rests>"));
+
+        assertTrue(xml.contains("<param name=\"header_letter\" type=\"query\" 
description=\"header param description2\""
+                + " defaultValue=\"b\" required=\"false\" 
collectionFormat=\"multi\" dataType=\"string\" access=\"acc2\">"));
+        assertTrue(xml.contains("<param name=\"header_count\" type=\"header\" 
description=\"header param description1\" "
+                + "defaultValue=\"1\" required=\"true\" dataType=\"integer\" 
access=\"acc1\">"));
+        assertTrue(xml.contains("<value>1</value>"));
+        assertTrue(xml.contains("<value>a</value>"));
+
+        assertTrue(xml.contains("<responseMessage code=\"300\" message=\"test 
msg\" responseModel=\"java.lang.Integer\"/>"));
+
+        String xml2 = (String) mbeanServer.invoke(on, "dumpRoutesAsXml", null, 
null);
+        log.info(xml2);
+        // and we should have rest in the routes that indicate its from a rest 
dsl
+        assertTrue(xml2.contains("rest=\"true\""));
+
+        // there should be 3 + 2 routes
+        assertEquals(3 + 2, context.getRouteDefinitions().size());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                restConfiguration().host("localhost");
+                rest("{{foo}}")
+                    .get().to("direct:hello");
+
+                rest("{{bar}}")
+                    .get().consumes("application/json")
+                        
.param().type(RestParamType.header).description("header param 
description1").dataType("integer").allowableValues(Arrays.asList("1", "2", "3", 
"4"))
+                            
.defaultValue("1").name("header_count").required(true).access("acc1")
+                        .endParam().
+                        param().type(RestParamType.query).description("header 
param description2").dataType("string").allowableValues(Arrays.asList("a", "b", 
"c", "d"))
+                            
.defaultValue("b").collectionFormat(CollectionFormat.multi).name("header_letter").required(false).access("acc2")
+                        .endParam()
+                        .responseMessage().code(300).message("test 
msg").responseModel(Integer.class).endResponseMessage()
+                        .to("direct:bye")
+                    .post().to("mock:update");
+
+                from("direct:hello")
+                    .transform().constant("Hello World");
+
+                from("direct:bye")
+                    .transform().constant("Bye World");
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/84640611/camel-core/src/test/java/org/apache/camel/management/ManagedRouteDumpRouteAsXmlPlaceholderTest.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/test/java/org/apache/camel/management/ManagedRouteDumpRouteAsXmlPlaceholderTest.java
 
b/camel-core/src/test/java/org/apache/camel/management/ManagedRouteDumpRouteAsXmlPlaceholderTest.java
new file mode 100644
index 0000000..0bf976f
--- /dev/null
+++ 
b/camel-core/src/test/java/org/apache/camel/management/ManagedRouteDumpRouteAsXmlPlaceholderTest.java
@@ -0,0 +1,96 @@
+/**
+ * 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.management;
+
+import java.util.Set;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.component.properties.PropertiesComponent;
+import org.apache.camel.component.rest.DummyRestConsumerFactory;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.SimpleRegistry;
+
+/**
+ * @version 
+ */
+public class ManagedRouteDumpRouteAsXmlPlaceholderTest extends 
ManagementTestSupport {
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext answer = super.createCamelContext();
+
+        PropertiesComponent pc = new PropertiesComponent();
+        
pc.setLocation("classpath:org/apache/camel/management/rest.properties");
+        answer.addComponent("properties", pc);
+
+        return answer;
+    }
+
+    public void testDumpAsXml() throws Exception {
+        // JMX tests dont work well on AIX CI servers (hangs them)
+        if (isPlatform("aix")) {
+            return;
+        }
+
+        MBeanServer mbeanServer = getMBeanServer();
+        ObjectName on = getRouteObjectName(mbeanServer);
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedBodiesReceived("Hello World");
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+
+        // should be started
+        String routeId = (String) mbeanServer.getAttribute(on, "RouteId");
+        assertEquals("myRoute", routeId);
+
+        String xml = (String) mbeanServer.invoke(on, "dumpRouteAsXml", new 
Object[]{true}, new String[]{"boolean"});
+        assertNotNull(xml);
+        log.info(xml);
+
+        assertTrue(xml.contains("direct:start"));
+        assertTrue(xml.contains("route"));
+        assertTrue(xml.contains("myRoute"));
+        assertTrue(xml.contains("mock:result"));
+    }
+
+    static ObjectName getRouteObjectName(MBeanServer mbeanServer) throws 
Exception {
+        Set<ObjectName> set = mbeanServer.queryNames(new 
ObjectName("*:type=routes,*"), null);
+        assertEquals(1, set.size());
+
+        return set.iterator().next();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("{{start}}").routeId("myRoute")
+                    .log("Got ${body}")
+                    .to("{{result}}");
+            }
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/84640611/camel-core/src/test/resources/org/apache/camel/management/rest.properties
----------------------------------------------------------------------
diff --git 
a/camel-core/src/test/resources/org/apache/camel/management/rest.properties 
b/camel-core/src/test/resources/org/apache/camel/management/rest.properties
new file mode 100644
index 0000000..d00c3b1
--- /dev/null
+++ b/camel-core/src/test/resources/org/apache/camel/management/rest.properties
@@ -0,0 +1,22 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+foo=/say/hello
+bar=/say/bye
+
+start=direct:start
+result=mock:result
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/84640611/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerSupport.java
----------------------------------------------------------------------
diff --git 
a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerSupport.java
 
b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerSupport.java
index f96e398..7b51ada 100644
--- 
a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerSupport.java
+++ 
b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerSupport.java
@@ -123,6 +123,7 @@ public class RestSwaggerSupport {
 
     public List<RestDefinition> getRestDefinitions(String camelId) throws 
Exception {
         ObjectName found = null;
+        boolean supportResolvePlaceholder = false;
 
         MBeanServer server = ManagementFactory.getPlatformMBeanServer();
         Set<ObjectName> names = server.queryNames(new 
ObjectName("org.apache.camel:type=context,*"), null);
@@ -137,11 +138,19 @@ public class RestSwaggerSupport {
                 if (CamelVersionHelper.isGE("2.15.0", version)) {
                     found = on;
                 }
+                if (CamelVersionHelper.isGE("2.15.3", version)) {
+                    supportResolvePlaceholder = true;
+                }
             }
         }
 
         if (found != null) {
-            String xml = (String) server.invoke(found, "dumpRestsAsXml", null, 
null);
+            String xml;
+            if (supportResolvePlaceholder) {
+                xml = (String) server.invoke(found, "dumpRestsAsXml", new 
Object[]{true}, new String[]{"boolean"});
+            } else {
+                xml = (String) server.invoke(found, "dumpRestsAsXml", null, 
null);
+            }
             if (xml != null) {
                 RestsDefinition rests = ModelHelper.createModelFromXml(null, 
xml, RestsDefinition.class);
                 if (rests != null) {

http://git-wip-us.apache.org/repos/asf/camel/blob/84640611/components/camel-swagger-java/src/test/java/org/apache/camel/swagger/RestSwaggerReaderPropertyPlaceholderTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-swagger-java/src/test/java/org/apache/camel/swagger/RestSwaggerReaderPropertyPlaceholderTest.java
 
b/components/camel-swagger-java/src/test/java/org/apache/camel/swagger/RestSwaggerReaderPropertyPlaceholderTest.java
new file mode 100644
index 0000000..a4ec368
--- /dev/null
+++ 
b/components/camel-swagger-java/src/test/java/org/apache/camel/swagger/RestSwaggerReaderPropertyPlaceholderTest.java
@@ -0,0 +1,108 @@
+/**
+ * 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.swagger;
+
+import java.util.List;
+import java.util.Properties;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import io.swagger.jaxrs.config.BeanConfig;
+import io.swagger.models.Swagger;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.DefaultClassResolver;
+import org.apache.camel.impl.JndiRegistry;
+import org.apache.camel.model.rest.RestDefinition;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class RestSwaggerReaderPropertyPlaceholderTest extends CamelTestSupport 
{
+
+    @Override
+    protected boolean useJmx() {
+        return true;
+    }
+
+    @Override
+    protected JndiRegistry createRegistry() throws Exception {
+        JndiRegistry jndi = super.createRegistry();
+        jndi.bind("dummy-rest", new DummyRestConsumerFactory());
+        return jndi;
+    }
+
+    @Override
+    protected Properties useOverridePropertiesWithPropertiesComponent() {
+        Properties prop = new Properties();
+        prop.put("foo", "hello");
+        prop.put("bar", "bye");
+        return prop;
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                
rest("/{{foo}}").consumes("application/json").produces("application/json")
+                        .get("/hi/{name}").description("Saying hi")
+                            
.param().name("name").type(RestParamType.path).dataType("string").description("Who
 is it").endParam()
+                            .to("log:hi")
+                        .get("/{{bar}}/{name}").description("Saying bye")
+                            
.param().name("name").type(RestParamType.path).dataType("string").description("Who
 is it").endParam()
+                            .responseMessage().code(200).message("A reply 
message").endResponseMessage()
+                            .to("log:bye")
+                        .post("/{{bar}}").description("To update the greeting 
message").consumes("application/xml").produces("application/xml")
+                            
.param().name("greeting").type(RestParamType.body).dataType("string").description("Message
 to use as greeting").endParam()
+                            .to("log:bye");
+            }
+        };
+    }
+
+    @Test
+    public void testReaderRead() throws Exception {
+        BeanConfig config = new BeanConfig();
+        config.setHost("localhost:8080");
+        config.setSchemes(new String[]{"http"});
+        config.setBasePath("/api");
+        RestSwaggerReader reader = new RestSwaggerReader();
+
+        RestSwaggerSupport support = new RestSwaggerSupport();
+        List<RestDefinition> rests = 
support.getRestDefinitions(context.getName());
+
+        Swagger swagger = reader.read(rests, null, config, context.getName(), 
new DefaultClassResolver());
+        assertNotNull(swagger);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+        String json = mapper.writeValueAsString(swagger);
+
+        log.info(json);
+
+        assertTrue(json.contains("\"host\" : \"localhost:8080\""));
+        assertTrue(json.contains("\"basePath\" : \"/api\""));
+        assertTrue(json.contains("\"/hello/bye\""));
+        assertTrue(json.contains("\"summary\" : \"To update the greeting 
message\""));
+        assertTrue(json.contains("\"/hello/bye/{name}\""));
+        assertTrue(json.contains("\"/hello/hi/{name}\""));
+
+        context.stop();
+    }
+
+}

Reply via email to