/**
 * 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.jolokia;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.management.InstanceNotFoundException;
import javax.management.ObjectName;

import org.apache.camel.commands.AbstractCamelController;

import org.jolokia.client.J4pClient;
import org.jolokia.client.exception.J4pException;
import org.jolokia.client.exception.J4pRemoteException;
import org.jolokia.client.request.J4pExecRequest;
import org.jolokia.client.request.J4pExecResponse;
import org.jolokia.client.request.J4pReadRequest;
import org.jolokia.client.request.J4pReadResponse;
import org.jolokia.client.request.J4pSearchRequest;
import org.jolokia.client.request.J4pSearchResponse;
import org.jolokia.client.request.J4pVersionRequest;
import org.jolokia.client.request.J4pVersionResponse;
import org.json.simple.JSONObject;

/**
 * A {@link org.apache.camel.commands.CamelController} that uses Jolokia Client to connect to remote JVMs which
 * has an Jolokia agent running.
 */
public class DefaultJolokiaCamelController extends AbstractCamelController implements JolokiaCamelController {

    private Map<String, ObjectName> cache = new HashMap<String, ObjectName>(100);

    private J4pClient jolokia;
    private String url;

    private ObjectName lookupCamelContext(String camelContextName) throws Exception {
        ObjectName on = cache.get(camelContextName);
        if (on == null) {
            ObjectName found = null;
            J4pSearchResponse sr = jolokia.execute(new J4pSearchRequest("*:type=context,*"));
            if (sr != null) {
                for (ObjectName name : sr.getObjectNames()) {
                    String id = name.getKeyProperty("name");
                    id = removeLeadingAndEndingQuotes(id);
                    if (camelContextName.equals(id)) {
                        found = name;
                        break;
                    }
                }
            }
            if (found != null) {
                on = found;
                cache.put(camelContextName, on);
            }
        }
        return on;
    }

    @Override
    public void using(J4pClient client) {
        this.jolokia = client;
        this.url = null;
    }

    @Override
    public void connect(String url, String username, String password) throws Exception {
        this.jolokia = JolokiaClientFactory.createJolokiaClient(url, username, password);
        this.url = url;
    }

    @Override
    public boolean ping() {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        J4pVersionResponse vr;
        try {
            vr = jolokia.execute(new J4pVersionRequest());
            return vr != null && vr.getValue() != null;
        } catch (J4pException e) {
            return false;
        }
    }

    @Override
    public Map<String, Object> getCamelContextInformation(String camelContextName) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        Map<String, Object> answer = new LinkedHashMap<String, Object>();

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {

            String pattern = String.format("%s:context=%s,type=services,name=DefaultTypeConverter", found.getDomain(), found.getKeyProperty("context"));
            ObjectName tc = ObjectName.getInstance(pattern);

            String pattern2 = String.format("%s:context=%s,type=services,name=DefaultAsyncProcessorAwaitManager", found.getDomain(), found.getKeyProperty("context"));
            ObjectName am = ObjectName.getInstance(pattern2);

            List<J4pReadRequest> list = new ArrayList<J4pReadRequest>();
            list.add(new J4pReadRequest(found));
            list.add(new J4pReadRequest(tc));
            list.add(new J4pReadRequest(am));

            List<J4pReadResponse> rr = jolokia.execute(list);
            if (rr != null && rr.size() > 0) {
                // camel context attributes
                J4pReadResponse first = rr.get(0);
                for (String key : first.getAttributes()) {
                    answer.put(asKey(key), first.getValue(key));
                }

                // type converter attributes
                if (rr.size() >= 2) {
                    J4pReadResponse second = rr.get(1);
                    for (String key : second.getAttributes()) {
                        answer.put("typeConverter." + asKey(key), second.getValue(key));
                    }
                }

                // async processor await manager attributes
                if (rr.size() >= 3) {
                    J4pReadResponse second = rr.get(2);
                    for (String key : second.getAttributes()) {
                        answer.put("asyncProcessorAwaitManager." + asKey(key), second.getValue(key));
                    }
                }
            }

            // would be great if there was an api in jolokia to read optional (eg ignore if an mbean does not exists)
            answer.put("streamCachingEnabled", false);
            try {
                pattern = String.format("%s:context=%s,type=services,name=DefaultStreamCachingStrategy", found.getDomain(), found.getKeyProperty("context"));
                ObjectName sc = ObjectName.getInstance(pattern);

                // there is only a mbean if stream caching is enabled
                J4pReadResponse rsc = jolokia.execute(new J4pReadRequest(sc));
                if (rsc != null) {
                    for (String key : rsc.getAttributes()) {
                        answer.put("streamCaching." + asKey(key), rsc.getValue(key));
                    }
                }
                answer.put("streamCachingEnabled", true);
            } catch (J4pRemoteException e) {
                // ignore
                boolean ignore = InstanceNotFoundException.class.getName().equals(e.getErrorType());
                if (!ignore) {
                    throw e;
                }
            }

            // store some data using special names as that is what the core-commands expects
            answer.put("name", answer.get("camelId"));
            answer.put("status", answer.get("state"));
            answer.put("version", answer.get("camelVersion"));
            answer.put("suspended", "Suspended".equals(answer.get("state")));
            TimeUnit unit = TimeUnit.valueOf((String) answer.get("timeUnit"));
            long timeout = (Long) answer.get("timeout");
            answer.put("shutdownTimeout", "" + unit.toSeconds(timeout));
            answer.put("applicationContextClassLoader", answer.get("applicationContextClassName"));
        }

        return answer;
    }

    @Override
    public List<Map<String, String>> getCamelContexts() throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        List<Map<String, String>> answer = new ArrayList<Map<String, String>>();

        J4pSearchResponse sr = jolokia.execute(new J4pSearchRequest("*:type=context,*"));

        List<J4pReadRequest> list = new ArrayList<J4pReadRequest>();
        for (ObjectName on : sr.getObjectNames()) {
            list.add(new J4pReadRequest(on, "CamelId", "State", "Uptime", "ExchangesTotal", "ExchangesInflight", "ExchangesFailed"));
        }

        List<J4pReadResponse> lrr = jolokia.execute(list);
        for (J4pReadResponse rr : lrr) {
            Map<String, String> row = new LinkedHashMap<String, String>();
            row.put("name", rr.getValue("CamelId").toString());
            row.put("state", rr.getValue("State").toString());
            row.put("uptime", rr.getValue("Uptime").toString());
            row.put("exchangesTotal", rr.getValue("ExchangesTotal").toString());
            row.put("exchangesInflight", rr.getValue("ExchangesInflight").toString());
            row.put("exchangesFailed", rr.getValue("ExchangesFailed").toString());
            answer.add(row);
        }

        return answer;
    }

    @Override
    public String getCamelContextStatsAsXml(String camelContextName, boolean fullStats, boolean includeProcessors) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            J4pExecResponse er = jolokia.execute(new J4pExecRequest(found, "dumpRoutesStatsAsXml(boolean,boolean)", fullStats, includeProcessors));
            if (er != null) {
                String xml = er.getValue();
                return xml;
            }
        }

        return null;
    }

    @Override
    public List<Map<String, Object>> browseInflightExchanges(String camelContextName, int limit, boolean sortByLongestDuration) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        List<Map<String, Object>> answer = new ArrayList<Map<String, Object>>();

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            String pattern = String.format("%s:context=%s,type=services,name=DefaultInflightRepository", found.getDomain(), found.getKeyProperty("context"));
            ObjectName on = ObjectName.getInstance(pattern);
            J4pExecResponse er = jolokia.execute(new J4pExecRequest(on, "browse(int,boolean)", limit, sortByLongestDuration));
            if (er != null) {
                JSONObject data = er.getValue();
                if (data != null) {
                    for (Object obj : data.values()) {
                        JSONObject inflight = (JSONObject) obj;

                        Map<String, Object> row = new LinkedHashMap<String, Object>();
                        row.put("exchangeId", asString(inflight.get("exchangeId")));
                        row.put("fromRouteId", asString(inflight.get("fromRouteId")));
                        row.put("routeId", asString(inflight.get("routeId")));
                        row.put("nodeId", asString(inflight.get("nodeId")));
                        row.put("elapsed", asString(inflight.get("elapsed")));
                        row.put("duration", asString(inflight.get("duration")));
                        answer.add(row);
                    }
                }
            }
        }

        return answer;
    }

    @Override
    public void startContext(String camelContextName) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            jolokia.execute(new J4pExecRequest(found, "start"));
        }
    }

    @Override
    public void stopContext(String camelContextName) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            jolokia.execute(new J4pExecRequest(found, "stop"));
        }
    }

    @Override
    public void suspendContext(String camelContextName) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            jolokia.execute(new J4pExecRequest(found, "suspend"));
        }
    }

    @Override
    public void resumeContext(String camelContextName) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            jolokia.execute(new J4pExecRequest(found, "resume"));
        }
    }

    @Override
    public List<Map<String, String>> getRoutes(String camelContextName) throws Exception {
        return getRoutes(camelContextName, null);
    }

    @Override
    public List<Map<String, String>> getRoutes(String camelContextName, String filter) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        List<Map<String, String>> answer = new ArrayList<Map<String, String>>();

        ObjectName found = camelContextName != null ? lookupCamelContext(camelContextName) : null;
        if (found != null) {

            String pattern = String.format("%s:context=%s,type=routes,*", found.getDomain(), found.getKeyProperty("context"));
            J4pSearchResponse sr = jolokia.execute(new J4pSearchRequest(pattern));

            List<J4pReadRequest> list = new ArrayList<J4pReadRequest>();
            for (ObjectName on : sr.getObjectNames()) {
                list.add(new J4pReadRequest(on, "CamelId", "RouteId", "State", "Uptime", "ExchangesTotal", "ExchangesInflight", "ExchangesFailed"));
            }

            List<J4pReadResponse> lrr = jolokia.execute(list);
            for (J4pReadResponse rr : lrr) {
                String routeId = rr.getValue("RouteId").toString();
                if (filter == null || routeId.matches(filter)) {
                    Map<String, String> row = new LinkedHashMap<String, String>();
                    row.put("camelContextName", rr.getValue("CamelId").toString());
                    row.put("routeId", routeId);
                    row.put("state", rr.getValue("State").toString());
                    row.put("uptime", rr.getValue("Uptime").toString());
                    row.put("exchangesTotal", rr.getValue("ExchangesTotal").toString());
                    row.put("exchangesInflight", rr.getValue("ExchangesInflight").toString());
                    row.put("exchangesFailed", rr.getValue("ExchangesFailed").toString());
                    answer.add(row);
                }
            }

        } else {
            List<Map<String, String>> camelContexts = this.getCamelContexts();
            for (Map<String, String> row : camelContexts) {
                List<Map<String, String>> routes = getRoutes(row.get("name"), filter);
                answer.addAll(routes);
            }
        }

        // sort the list
        Collections.sort(answer, new Comparator<Map<String, String>>() {
            @Override
            public int compare(Map<String, String> o1, Map<String, String> o2) {
                // group by camel context first, then by route name
                String c1 = o1.get("camelContextName");
                String c2 = o2.get("camelContextName");

                int answer = c1.compareTo(c2);
                if (answer == 0) {
                    // okay from same camel context, then sort by route id
                    answer = o1.get("routeId").compareTo(o2.get("routeId"));
                }
                return answer;
            }
        });
        return answer;
    }

    @Override
    public void resetRouteStats(String camelContextName) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        ObjectName found = lookupCamelContext(camelContextName);

        if (found != null) {
            String pattern = String.format("%s:context=%s,type=routes,name=*", found.getDomain(), found.getKeyProperty("context"));
            J4pSearchResponse sr = jolokia.execute(new J4pSearchRequest(pattern));

            List<J4pExecRequest> list = new ArrayList<J4pExecRequest>();
            for (ObjectName on : sr.getObjectNames()) {
                list.add(new J4pExecRequest(on, "reset(boolean)", true));
            }

            jolokia.execute(list);
        }
    }

    @Override
    public void startRoute(String camelContextName, String routeId) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            String pattern = String.format("%s:context=%s,type=routes,name=\"%s\"", found.getDomain(), found.getKeyProperty("context"), routeId);
            ObjectName on = ObjectName.getInstance(pattern);
            jolokia.execute(new J4pExecRequest(on, "start()"));
        }
    }

    @Override
    public void stopRoute(String camelContextName, String routeId) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            String pattern = String.format("%s:context=%s,type=routes,name=\"%s\"", found.getDomain(), found.getKeyProperty("context"), routeId);
            ObjectName on = ObjectName.getInstance(pattern);
            jolokia.execute(new J4pExecRequest(on, "stop()"));
        }
    }

    @Override
    public void suspendRoute(String camelContextName, String routeId) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            String pattern = String.format("%s:context=%s,type=routes,name=\"%s\"", found.getDomain(), found.getKeyProperty("context"), routeId);
            ObjectName on = ObjectName.getInstance(pattern);
            jolokia.execute(new J4pExecRequest(on, "suspend()"));
        }
    }

    @Override
    public void resumeRoute(String camelContextName, String routeId) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            String pattern = String.format("%s:context=%s,type=routes,name=\"%s\"", found.getDomain(), found.getKeyProperty("context"), routeId);
            ObjectName on = ObjectName.getInstance(pattern);
            jolokia.execute(new J4pExecRequest(on, "resume()"));
        }
    }

    @Override
    public String getRouteModelAsXml(String routeId, String camelContextName) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            String pattern = String.format("%s:context=%s,type=routes,name=\"%s\"", found.getDomain(), found.getKeyProperty("context"), routeId);
            ObjectName on = ObjectName.getInstance(pattern);
            J4pExecResponse response = jolokia.execute(new J4pExecRequest(on, "dumpRouteAsXml()"));
            if (response != null) {
                String xml = response.getValue();
                return xml;
            }
        }

        return null;
    }

    @Override
    public String getRouteStatsAsXml(String routeId, String camelContextName, boolean fullStats, boolean includeProcessors) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            String pattern = String.format("%s:context=%s,type=routes,name=\"%s\"", found.getDomain(), found.getKeyProperty("context"), routeId);
            ObjectName on = ObjectName.getInstance(pattern);
            J4pExecResponse response = jolokia.execute(new J4pExecRequest(on, "dumpRouteStatsAsXml(boolean,boolean)", fullStats, includeProcessors));
            if (response != null) {
                String xml = response.getValue();
                return xml;
            }
        }

        return null;
    }

    @Override
    public String getRestModelAsXml(String camelContextName) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            J4pExecResponse response = jolokia.execute(new J4pExecRequest(found, "dumpRestsAsXml()"));
            if (response != null) {
                String xml = response.getValue();
                return xml;
            }
        }

        return null;
    }

    @Override
    public String getRestApiDocAsJson(String camelContextName) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            String pattern = String.format("%s:context=%s,type=services,name=DefaultRestRegistry", found.getDomain(), found.getKeyProperty("context"));
            ObjectName on = ObjectName.getInstance(pattern);

            J4pExecResponse response = jolokia.execute(new J4pExecRequest(on, "apiDocAsJson()"));
            if (response != null) {
                String json = response.getValue();
                return json;
            }
        }

        return null;
    }

    @Override
    public List<Map<String, String>> getEndpoints(String camelContextName) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        List<Map<String, String>> answer = new ArrayList<Map<String, String>>();

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            String pattern = String.format("%s:context=%s,type=endpoints,*", found.getDomain(), found.getKeyProperty("context"));
            J4pSearchResponse sr = jolokia.execute(new J4pSearchRequest(pattern));

            List<J4pReadRequest> list = new ArrayList<J4pReadRequest>();
            for (ObjectName on : sr.getObjectNames()) {
                list.add(new J4pReadRequest(on, "CamelId", "EndpointUri", "State"));
            }

            List<J4pReadResponse> lrr = jolokia.execute(list);
            for (J4pReadResponse rr : lrr) {
                Map<String, String> row = new LinkedHashMap<String, String>();
                row.put("camelContextName", rr.getValue("CamelId").toString());
                row.put("uri", rr.getValue("EndpointUri").toString());
                row.put("state", rr.getValue("State").toString());
                answer.add(row);
            }
        }

        return answer;
    }

    @Override
    public List<Map<String, String>> getEndpointRuntimeStatistics(String camelContextName) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        List<Map<String, String>> answer = new ArrayList<Map<String, String>>();

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            String pattern = String.format("%s:context=%s,type=services,name=DefaultRuntimeEndpointRegistry", found.getDomain(), found.getKeyProperty("context"));
            ObjectName on = ObjectName.getInstance(pattern);

            J4pExecResponse response = jolokia.execute(new J4pExecRequest(on, "endpointStatistics()"));
            if (response != null) {
                JSONObject data = response.getValue();
                for (Object obj : data.values()) {
                    JSONObject data2 = (JSONObject) obj;
                    JSONObject service = (JSONObject) data2.values().iterator().next();

                    Map<String, String> row = new LinkedHashMap<String, String>();
                    row.put("index", asString(service.get("index")));
                    row.put("url", asString(service.get("url")));
                    row.put("routeId", asString(service.get("routeId")));
                    row.put("direction", asString(service.get("direction")));
                    row.put("static", asString(service.get("static")));
                    row.put("dynamic", asString(service.get("dynamic")));
                    row.put("hits", asString(service.get("hits")));
                    answer.add(row);
                }
            }

            // sort the list
            Collections.sort(answer, new Comparator<Map<String, String>>() {
                @Override
                public int compare(Map<String, String> endpoint1, Map<String, String> endpoint2) {
                    // sort by route id
                    String route1 = endpoint1.get("routeId");
                    String route2 = endpoint2.get("routeId");
                    int num = route1.compareTo(route2);
                    if (num == 0) {
                        // we want in before out
                        String dir1 = endpoint1.get("direction");
                        String dir2 = endpoint2.get("direction");
                        num = dir1.compareTo(dir2);
                    }
                    return num;
                }

            });
        }

        return answer;
    }

    @Override
    public List<Map<String, String>> getRestServices(String camelContextName) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        List<Map<String, String>> answer = new ArrayList<Map<String, String>>();

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            String pattern = String.format("%s:context=%s,type=services,name=DefaultRestRegistry", found.getDomain(), found.getKeyProperty("context"));
            ObjectName on = ObjectName.getInstance(pattern);

            J4pExecResponse response = jolokia.execute(new J4pExecRequest(on, "listRestServices()"));
            if (response != null) {
                JSONObject data = response.getValue();
                if (data != null) {
                    for (Object obj : data.values()) {
                        JSONObject data2 = (JSONObject) obj;
                        JSONObject service = (JSONObject) data2.values().iterator().next();

                        Map<String, String> row = new LinkedHashMap<String, String>();
                        row.put("basePath", asString(service.get("basePath")));
                        row.put("baseUrl", asString(service.get("baseUrl")));
                        row.put("consumes", asString(service.get("consumes")));
                        row.put("description", asString(service.get("description")));
                        row.put("inType", asString(service.get("inType")));
                        row.put("method", asString(service.get("method")));
                        row.put("outType", asString(service.get("outType")));
                        row.put("produces", asString(service.get("produces")));
                        row.put("routeId", asString(service.get("routeId")));
                        row.put("state", asString(service.get("state")));
                        row.put("uriTemplate", asString(service.get("uriTemplate")));
                        row.put("url", asString(service.get("url")));
                        answer.add(row);
                    }
                }
            }

            // sort the list
            Collections.sort(answer, new Comparator<Map<String, String>>() {
                @Override
                public int compare(Map<String, String> service1, Map<String, String> service2) {
                    String url1 = service1.get("url");
                    String url2 = service2.get("url");
                    return url1.compareTo(url2);
                }
            });
        }

        return answer;
    }

    @Override
    public String explainEndpointAsJSon(String camelContextName, String uri, boolean allOptions) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            J4pExecResponse response = jolokia.execute(new J4pExecRequest(found, "explainEndpointJson(java.lang.String,boolean)", uri, allOptions));
            if (response != null) {
                String json = response.getValue();
                return json;
            }
        }

        return null;
    }

    @Override
    public String explainEipAsJSon(String camelContextName, String nameOrId, boolean allOptions) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            J4pExecResponse response = jolokia.execute(new J4pExecRequest(found, "explainEipJson(java.lang.String,boolean)", nameOrId, allOptions));
            if (response != null) {
                String json = response.getValue();
                return json;
            }
        }

        return null;
    }

    @Override
    public List<Map<String, String>> listComponents(String camelContextName) throws Exception {
        if (jolokia == null) {
            throw new IllegalStateException("Need to connect to remote jolokia first");
        }

        List<Map<String, String>> answer = new ArrayList<Map<String, String>>();

        ObjectName found = lookupCamelContext(camelContextName);
        if (found != null) {
            J4pExecResponse response = jolokia.execute(new J4pExecRequest(found, "listComponents()"));
            if (response != null) {
                JSONObject data = response.getValue();
                for (Object obj : data.values()) {
                    JSONObject component = (JSONObject) obj;

                    Map<String, String> row = new LinkedHashMap<String, String>();
                    row.put("artifactId", asString(component.get("artifactId")));
                    row.put("title", asString(component.get("title")));
                    row.put("description", asString(component.get("description")));
                    row.put("groupId", asString(component.get("groupId")));
                    row.put("label", asString(component.get("label")));
                    row.put("name", asString(component.get("name")));
                    row.put("status", asString(component.get("status")));
                    row.put("type", asString(component.get("type")));
                    row.put("version", asString(component.get("version")));
                    answer.add(row);
                }
            }

            // sort the list
            Collections.sort(answer, new Comparator<Map<String, String>>() {
                @Override
                public int compare(Map<String, String> component1, Map<String, String> component2) {
                    String name1 = component1.get("name");
                    String name2 = component2.get("name");
                    return name1.compareTo(name2);
                }
            });
        }

        return answer;
    }

    private static String asKey(String attributeKey) {
        char ch = Character.toLowerCase(attributeKey.charAt(0));
        return ch + attributeKey.substring(1);
    }

    private static String asString(Object basePath) {
        if (basePath == null) {
            return null;
        } else {
            return basePath.toString();
        }
    }

    private static String removeLeadingAndEndingQuotes(String s) {
        if (s == null || s.isEmpty()) {
            return s;
        }

        String copy = s.trim();
        if (copy.startsWith("'") && copy.endsWith("'")) {
            return copy.substring(1, copy.length() - 1);
        }
        if (copy.startsWith("\"") && copy.endsWith("\"")) {
            return copy.substring(1, copy.length() - 1);
        }

        // no quotes, so return as-is
        return s;
    }

}
