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 2017/01/05 13:28:37 UTC

camel git commit: CAMEL-10530 Add TransformerListCommand

Repository: camel
Updated Branches:
  refs/heads/master efc735119 -> cb22a5661


CAMEL-10530 Add TransformerListCommand


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

Branch: refs/heads/master
Commit: cb22a566171bdf07bab6010448181ec2d60be65b
Parents: efc7351
Author: Tomohisa Igarashi <tm...@gmail.com>
Authored: Thu Jan 5 20:44:31 2017 +0900
Committer: Claus Ibsen <da...@apache.org>
Committed: Thu Jan 5 14:28:28 2017 +0100

----------------------------------------------------------------------
 .../java/org/apache/camel/CamelContext.java     |   7 +
 .../apache/camel/impl/DefaultCamelContext.java  |   5 +
 .../java/org/apache/camel/spi/Transformer.java  |   2 +-
 .../commands/AbstractLocalCamelController.java  |  24 +++
 .../apache/camel/commands/CamelController.java  |   8 +
 .../camel/commands/TransformerListCommand.java  | 203 +++++++++++++++++++
 .../AbstractLocalCamelControllerTest.java       |  29 +++
 .../commands/TransformerListCommandTest.java    | 119 +++++++++++
 8 files changed, 396 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/cb22a566/camel-core/src/main/java/org/apache/camel/CamelContext.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/CamelContext.java b/camel-core/src/main/java/org/apache/camel/CamelContext.java
index c827748..72ad8a5 100644
--- a/camel-core/src/main/java/org/apache/camel/CamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/CamelContext.java
@@ -73,6 +73,7 @@ import org.apache.camel.spi.ServicePool;
 import org.apache.camel.spi.ShutdownStrategy;
 import org.apache.camel.spi.StreamCachingStrategy;
 import org.apache.camel.spi.Transformer;
+import org.apache.camel.spi.TransformerRegistry;
 import org.apache.camel.spi.TypeConverterRegistry;
 import org.apache.camel.spi.UnitOfWorkFactory;
 import org.apache.camel.spi.UuidGenerator;
@@ -1252,6 +1253,12 @@ public interface CamelContext extends SuspendableService, RuntimeConfiguration {
     Transformer resolveTransformer(DataType from, DataType to);
 
     /**
+     * Gets the {@link org.apache.camel.spi.TransformerRegistry}
+     * @return the TransformerRegistry
+     */
+    TransformerRegistry getTransformerRegistry();
+
+    /**
      * Sets the properties that can be referenced in the camel context
      * <p/>
      * <b>Important:</b> This has nothing to do with property placeholders, and is just a plain set of key/value pairs

http://git-wip-us.apache.org/repos/asf/camel/blob/cb22a566/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index 5372b90..fa9c255 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -4292,6 +4292,11 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         return resolveTransformer(getTransformerKey(from, to));
     }
 
+    @Override
+    public TransformerRegistry getTransformerRegistry() {
+        return transformerRegistry;
+    }
+
     protected Map<String, RouteService> getRouteServices() {
         return routeServices;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/cb22a566/camel-core/src/main/java/org/apache/camel/spi/Transformer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/Transformer.java b/camel-core/src/main/java/org/apache/camel/spi/Transformer.java
index fe3bd90..da0b949 100644
--- a/camel-core/src/main/java/org/apache/camel/spi/Transformer.java
+++ b/camel-core/src/main/java/org/apache/camel/spi/Transformer.java
@@ -116,7 +116,7 @@ public abstract class Transformer extends ServiceSupport implements CamelContext
 
     @Override
     public String toString() {
-        return String.format("%s[model='%s', from='%s', to='%s']", this.getClass().getSimpleName(), from, to);
+        return String.format("%s[scheme='%s', from='%s', to='%s']", this.getClass().getSimpleName(), model, from, to);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/camel/blob/cb22a566/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractLocalCamelController.java
----------------------------------------------------------------------
diff --git a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractLocalCamelController.java b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractLocalCamelController.java
index 69699e9..237a9ff 100644
--- a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractLocalCamelController.java
+++ b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractLocalCamelController.java
@@ -46,6 +46,7 @@ import org.apache.camel.spi.EndpointRegistry;
 import org.apache.camel.spi.ManagementAgent;
 import org.apache.camel.spi.RestRegistry;
 import org.apache.camel.spi.RuntimeEndpointRegistry;
+import org.apache.camel.spi.Transformer;
 import org.apache.camel.util.JsonSchemaHelper;
 
 /**
@@ -622,6 +623,29 @@ public abstract class AbstractLocalCamelController extends AbstractCamelControll
         return answer;
     }
 
+    @Override
+    public List<Map<String, String>> getTransformers(String camelContextName) throws Exception {
+        List<Map<String, String>> answer = new ArrayList<Map<String, String>>();
+
+        if (camelContextName != null) {
+            CamelContext context = this.getLocalCamelContext(camelContextName);
+            if (context != null) {
+                List<Transformer> transformers = new ArrayList<Transformer>(context.getTransformerRegistry().values());
+                for (Transformer transformer : transformers) {
+                    Map<String, String> row = new LinkedHashMap<String, String>();
+                    row.put("camelContextName", context.getName());
+                    row.put("scheme", transformer.getModel());
+                    row.put("from", transformer.getFrom().toString());
+                    row.put("to", transformer.getTo().toString());
+                    row.put("state", transformer.getStatus().toString());
+                    row.put("description", transformer.toString());
+                    answer.add(row);
+                }
+            }
+        }
+        return answer;
+    }
+
     private static String getEndpointState(Endpoint endpoint) {
         // must use String type to be sure remote JMX can read the attribute without requiring Camel classes.
         if (endpoint instanceof StatefulService) {

http://git-wip-us.apache.org/repos/asf/camel/blob/cb22a566/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CamelController.java
----------------------------------------------------------------------
diff --git a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CamelController.java b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CamelController.java
index b813909..2cf70a4 100644
--- a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CamelController.java
+++ b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CamelController.java
@@ -368,4 +368,12 @@ public interface CamelController {
      */
     String catalogLanguageAsciiDoc(String name) throws Exception;
 
+    /**
+     * Return the transformers
+     *
+     * @param camelContextName the Camel context.
+     * @return a list of key/value pairs with transformer information
+     * @throws java.lang.Exception can be thrown
+     */
+    List<Map<String, String>> getTransformers(String camelContextName) throws Exception;
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/cb22a566/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/TransformerListCommand.java
----------------------------------------------------------------------
diff --git a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/TransformerListCommand.java b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/TransformerListCommand.java
new file mode 100644
index 0000000..29d07f3
--- /dev/null
+++ b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/TransformerListCommand.java
@@ -0,0 +1,203 @@
+/**
+ * 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.commands;
+
+import java.io.PrintStream;
+import java.net.URLDecoder;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.util.JsonSchemaHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.URISupport;
+
+/**
+ * List the Camel transformers available in the JVM.
+ */
+public class TransformerListCommand extends AbstractCamelCommand {
+
+    private static final String CONTEXT_NAME_COLUMN_LABEL = "Context";
+    private static final String SCHEME_COLUMN_LABEL = "Scheme";
+    private static final String FROM_COLUMN_LABEL = "From";
+    private static final String TO_COLUMN_LABEL = "To";
+    private static final String STATE_COLUMN_LABEL = "State";
+    private static final String DESCRIPTION_COLUMN_LABEL = "Description";
+
+    private static final int DEFAULT_COLUMN_WIDTH_INCREMENT = 0;
+    private static final String DEFAULT_FIELD_PREAMBLE = " ";
+    private static final String DEFAULT_FIELD_POSTAMBLE = " ";
+    private static final String DEFAULT_HEADER_PREAMBLE = " ";
+    private static final String DEFAULT_HEADER_POSTAMBLE = " ";
+    private static final int DEFAULT_FORMAT_BUFFER_LENGTH = 24;
+    // endpoint uris can be very long so clip by default after 120 chars
+    private static final int MAX_COLUMN_WIDTH = 120;
+    private static final int MIN_COLUMN_WIDTH = 12;
+
+    boolean decode = true;
+    boolean verbose;
+    boolean explain;
+    private final String context;
+
+    public TransformerListCommand(String context, boolean decode, boolean verbose, boolean explain) {
+        this.decode = decode;
+        this.verbose = verbose;
+        this.explain = explain;
+        this.context = context;
+    }
+
+    @Override
+    public Object execute(CamelController camelController, PrintStream out, PrintStream err) throws Exception {
+        final List<Map<String, String>> camelContextInfos = camelController.getCamelContexts(this.context);
+        final Map<String, List<Map<String, String>>> contextsToTransformers = new HashMap<>();
+        
+        for (Map<String, String> camelContextInfo : camelContextInfos) {
+            String camelContextName = camelContextInfo.get("name");
+            final List<Map<String, String>> transformers = camelController.getTransformers(camelContextName);
+            if (transformers.isEmpty()) {
+                continue;
+            }
+            contextsToTransformers.put(camelContextName, transformers);
+        }
+
+        final Map<String, Integer> columnWidths = computeColumnWidths(contextsToTransformers);
+        final String headerFormat = buildFormatString(columnWidths, true);
+        final String rowFormat = buildFormatString(columnWidths, false);
+
+        for (Map.Entry<String, List<Map<String, String>>> stringListEntry : contextsToTransformers.entrySet()) {
+            final String camelContextName = stringListEntry.getKey();
+            final List<Map<String, String>> transformers = stringListEntry.getValue();
+
+            if (verbose) {
+                out.println(String.format(headerFormat, CONTEXT_NAME_COLUMN_LABEL, SCHEME_COLUMN_LABEL, FROM_COLUMN_LABEL, TO_COLUMN_LABEL, STATE_COLUMN_LABEL, DESCRIPTION_COLUMN_LABEL));
+                out.println(String.format(headerFormat, "-------", "------", "----", "--", "-----", "-----------"));
+            } else {
+                out.println(String.format(headerFormat, CONTEXT_NAME_COLUMN_LABEL, SCHEME_COLUMN_LABEL, FROM_COLUMN_LABEL, TO_COLUMN_LABEL, STATE_COLUMN_LABEL));
+                out.println(String.format(headerFormat, "-------", "------", "----", "--", "-----"));
+            }
+            for (Map<String, String> row : transformers) {
+                String scheme = row.get("scheme");
+                String from = row.get("from");
+                String to = row.get("to");
+                String state = row.get("state");
+                if (verbose) {
+                    String desc = row.get("description");
+                    out.println(String.format(rowFormat, camelContextName, scheme, from, to, state, desc));
+                } else {
+                    out.println(String.format(rowFormat, camelContextName, scheme, from, to, state));
+                }
+            }
+        }
+        return null;
+    }
+
+    private Map<String, Integer> computeColumnWidths(final Map<String, List<Map<String, String>>> contextsToTransformers) throws Exception {
+        int maxCamelContextLen = 0;
+        int maxSchemeLen = 0;
+        int maxFromLen = 0;
+        int maxToLen = 0;
+        int maxStatusLen = 0;
+        int maxDescLen = 0;
+
+        for (Map.Entry<String, List<Map<String, String>>> stringListEntry : contextsToTransformers.entrySet()) {
+            final String camelContextName = stringListEntry.getKey();
+
+            maxCamelContextLen = java.lang.Math.max(maxCamelContextLen, camelContextName.length());
+            
+            final List<Map<String, String>> transformers = stringListEntry.getValue();
+
+
+            for (Map<String, String> row : transformers) {
+                String scheme = row.get("scheme");
+                maxSchemeLen = java.lang.Math.max(maxSchemeLen, scheme == null ? 0 : scheme.length());
+                String from = row.get("from");
+                maxFromLen = java.lang.Math.max(maxFromLen, from == null ? 0 : from.length());
+                String to = row.get("to");
+                maxToLen = java.lang.Math.max(maxToLen, to == null ? 0 : to.length());
+                String status = row.get("state");
+                maxStatusLen = java.lang.Math.max(maxStatusLen, status == null ? 0 : status.length());
+                if (verbose) {
+                    String desc = row.get("description");
+                    maxDescLen = java.lang.Math.max(maxDescLen, desc == null ? 0 : desc.length());
+                }
+            }
+        }
+    
+        final Map<String, Integer> retval = new Hashtable<>();
+        retval.put(CONTEXT_NAME_COLUMN_LABEL, maxCamelContextLen);
+        retval.put(SCHEME_COLUMN_LABEL, maxSchemeLen);
+        retval.put(FROM_COLUMN_LABEL, maxFromLen);
+        retval.put(TO_COLUMN_LABEL, maxToLen);
+        retval.put(STATE_COLUMN_LABEL, maxStatusLen);
+        if (verbose) {
+            retval.put(DESCRIPTION_COLUMN_LABEL, maxDescLen);
+        }
+
+        return retval;
+    }
+
+    private String buildFormatString(final Map<String, Integer> columnWidths, final boolean isHeader) {
+        final String fieldPreamble;
+        final String fieldPostamble;
+        final int columnWidthIncrement;
+
+        if (isHeader) {
+            fieldPreamble = DEFAULT_HEADER_PREAMBLE;
+            fieldPostamble = DEFAULT_HEADER_POSTAMBLE;
+        } else {
+            fieldPreamble = DEFAULT_FIELD_PREAMBLE;
+            fieldPostamble = DEFAULT_FIELD_POSTAMBLE;
+        }
+        columnWidthIncrement = DEFAULT_COLUMN_WIDTH_INCREMENT;
+
+        int ctxLen = java.lang.Math.min(columnWidths.get(CONTEXT_NAME_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth());
+        ctxLen = Math.max(MIN_COLUMN_WIDTH, ctxLen);
+        int schemeLen = java.lang.Math.min(columnWidths.get(SCHEME_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth());
+        schemeLen = Math.max(MIN_COLUMN_WIDTH, schemeLen);
+        int fromLen = java.lang.Math.min(columnWidths.get(FROM_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth());
+        fromLen = Math.max(MIN_COLUMN_WIDTH, fromLen);
+        int toLen = java.lang.Math.min(columnWidths.get(TO_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth());
+        toLen = Math.max(MIN_COLUMN_WIDTH, toLen);
+        int stateLen = -1;
+        if (verbose) {
+            stateLen = java.lang.Math.min(columnWidths.get(STATE_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth());
+            stateLen = Math.max(MIN_COLUMN_WIDTH, stateLen);
+        }
+        // last row does not have min width
+
+        final StringBuilder retval = new StringBuilder(DEFAULT_FORMAT_BUFFER_LENGTH);
+        retval.append(fieldPreamble).append("%-").append(ctxLen).append('.').append(ctxLen).append('s').append(fieldPostamble).append(' ');
+        retval.append(fieldPreamble).append("%-").append(schemeLen).append('.').append(schemeLen).append('s').append(fieldPostamble).append(' ');
+        retval.append(fieldPreamble).append("%-").append(fromLen).append('.').append(fromLen).append('s').append(fieldPostamble).append(' ');
+        retval.append(fieldPreamble).append("%-").append(toLen).append('.').append(toLen).append('s').append(fieldPostamble).append(' ');
+        if (verbose) {
+            retval.append(fieldPreamble).append("%-").append(stateLen).append('.').append(stateLen).append('s').append(fieldPostamble).append(' ');
+        }
+        retval.append(fieldPreamble).append("%s").append(fieldPostamble).append(' ');
+
+        return retval.toString();
+    }
+
+    private int getMaxColumnWidth() {
+        if (verbose) {
+            return Integer.MAX_VALUE;
+        } else {
+            return MAX_COLUMN_WIDTH;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/cb22a566/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/AbstractLocalCamelControllerTest.java
----------------------------------------------------------------------
diff --git a/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/AbstractLocalCamelControllerTest.java b/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/AbstractLocalCamelControllerTest.java
index 71886c1..0a24e2c 100644
--- a/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/AbstractLocalCamelControllerTest.java
+++ b/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/AbstractLocalCamelControllerTest.java
@@ -20,9 +20,13 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.Message;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.impl.ExplicitCamelContextNameStrategy;
+import org.apache.camel.model.transformer.CustomTransformerDefinition;
+import org.apache.camel.spi.DataType;
+import org.apache.camel.spi.Transformer;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -49,6 +53,11 @@ public class AbstractLocalCamelControllerTest {
             }
         });
 
+        CustomTransformerDefinition def = new CustomTransformerDefinition();
+        def.setType(DummyTransformer.class.getName());
+        def.setFrom("xml:foo");
+        def.setTo("json:bar");
+        context.getTransformers().add(def);
         localCamelController = new DummyCamelController(context);
     }
 
@@ -108,4 +117,24 @@ public class AbstractLocalCamelControllerTest {
 
         assertEquals("Context should contain one inflight exchange for specific route", 1, inflightExchanges.size());
     }
+
+    @Test
+    public void testTransformer() throws Exception {
+        context.resolveTransformer(new DataType("xml:foo"), new DataType("json:bar"));
+        List<Map<String, String>> transformers = localCamelController.getTransformers("context1");
+        assertEquals(1, transformers.size());
+        Map<String, String> dummyTransformer = transformers.get(0);
+        assertEquals("context1", dummyTransformer.get("camelContextName"));
+        assertEquals("DummyTransformer[scheme='null', from='xml:foo', to='json:bar']", dummyTransformer.get("description"));
+        assertEquals(null, dummyTransformer.get("scheme"));
+        assertEquals("xml:foo", dummyTransformer.get("from"));
+        assertEquals("json:bar", dummyTransformer.get("to"));
+        assertEquals("Started", dummyTransformer.get("state"));
+    }
+
+    public static class DummyTransformer extends Transformer {
+        @Override
+        public void transform(Message message, DataType from, DataType to) throws Exception {
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/cb22a566/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/TransformerListCommandTest.java
----------------------------------------------------------------------
diff --git a/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/TransformerListCommandTest.java b/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/TransformerListCommandTest.java
new file mode 100644
index 0000000..a826f5d
--- /dev/null
+++ b/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/TransformerListCommandTest.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.commands;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Message;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.ExplicitCamelContextNameStrategy;
+import org.apache.camel.model.dataformat.StringDataFormat;
+import org.apache.camel.model.transformer.CustomTransformerDefinition;
+import org.apache.camel.model.transformer.DataFormatTransformerDefinition;
+import org.apache.camel.model.transformer.EndpointTransformerDefinition;
+import org.apache.camel.spi.DataType;
+import org.apache.camel.spi.Transformer;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class TransformerListCommandTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(TransformerListCommandTest.class);
+
+    @Test
+    public void testTransformerList() throws Exception {
+        String out = doTest(false);
+        assertTrue(out.contains("xml:foo"));
+        assertTrue(out.contains("json:bar"));
+        assertTrue(out.contains("java:" + this.getClass().getName()));
+        assertTrue(out.contains("xml:test"));
+        assertTrue(out.contains("custom"));
+        assertTrue(out.contains("Started"));
+        assertFalse(out.contains("ProcessorTransformer["));
+        assertFalse(out.contains("DataFormatTransformer["));
+        assertFalse(out.contains("MyTransformer["));
+    }
+    
+    @Test
+    public void testTransformerListVerbose() throws Exception {
+        String out = doTest(true);
+        assertTrue(out.contains("xml:foo"));
+        assertTrue(out.contains("json:bar"));
+        assertTrue(out.contains("java:" + this.getClass().getName()));
+        assertTrue(out.contains("xml:test"));
+        assertTrue(out.contains("custom"));
+        assertTrue(out.contains("Started"));
+        assertTrue(out.contains("ProcessorTransformer["));
+        assertTrue(out.contains("DataFormatTransformer["));
+        assertTrue(out.contains("MyTransformer["));
+    }
+    
+    private String doTest(boolean verbose) throws Exception {
+        CamelContext context = new DefaultCamelContext();
+        EndpointTransformerDefinition etd = new EndpointTransformerDefinition();
+        etd.setFrom("xml:foo");
+        etd.setTo("json:bar");
+        etd.setUri("direct:transformer");
+        context.getTransformers().add(etd);
+        context.resolveTransformer(new DataType("xml:foo"), new DataType("json:bar"));
+        DataFormatTransformerDefinition dftd = new DataFormatTransformerDefinition();
+        dftd.setFrom(this.getClass());
+        dftd.setTo("xml:test");
+        dftd.setDataFormatType(new StringDataFormat());
+        context.getTransformers().add(dftd);
+        context.resolveTransformer(new DataType(this.getClass()), new DataType("xml:test"));
+        CustomTransformerDefinition ctd = new CustomTransformerDefinition();
+        ctd.setScheme("custom");
+        ctd.setType(MyTransformer.class.getName());
+        context.getTransformers().add(ctd);
+        context.resolveTransformer("custom");
+        context.setNameStrategy(new ExplicitCamelContextNameStrategy("foobar"));
+        context.start();
+
+        CamelController controller = new DummyCamelController(context);
+
+        OutputStream os = new ByteArrayOutputStream();
+        PrintStream ps = new PrintStream(os);
+
+        TransformerListCommand command = new TransformerListCommand(null, false, verbose, false);
+        command.execute(controller, ps, null);
+
+        String out = os.toString();
+        assertNotNull(out);
+        LOG.info("\n\n{}\n", out);
+
+        context.stop();
+        return out;
+    }
+
+    public static class MyTransformer extends Transformer {
+        @Override
+        public void transform(Message message, DataType from, DataType to) throws Exception {
+            return;
+        }
+    }
+}
+