001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.management.mbean;
018
019import java.io.ByteArrayInputStream;
020import java.io.IOException;
021import java.io.InputStream;
022import java.net.URLDecoder;
023import java.util.ArrayList;
024import java.util.Collection;
025import java.util.Collections;
026import java.util.Comparator;
027import java.util.List;
028import java.util.Map;
029import java.util.Properties;
030import java.util.Set;
031import java.util.concurrent.TimeUnit;
032import java.util.concurrent.atomic.AtomicBoolean;
033import javax.management.MBeanServer;
034import javax.management.ObjectName;
035import javax.management.openmbean.CompositeData;
036import javax.management.openmbean.CompositeDataSupport;
037import javax.management.openmbean.CompositeType;
038import javax.management.openmbean.TabularData;
039import javax.management.openmbean.TabularDataSupport;
040
041import org.w3c.dom.Document;
042
043import org.apache.camel.CamelContext;
044import org.apache.camel.Component;
045import org.apache.camel.ComponentConfiguration;
046import org.apache.camel.Endpoint;
047import org.apache.camel.ManagementStatisticsLevel;
048import org.apache.camel.Producer;
049import org.apache.camel.ProducerTemplate;
050import org.apache.camel.Route;
051import org.apache.camel.TimerListener;
052import org.apache.camel.api.management.ManagedResource;
053import org.apache.camel.api.management.mbean.CamelOpenMBeanTypes;
054import org.apache.camel.api.management.mbean.ManagedCamelContextMBean;
055import org.apache.camel.api.management.mbean.ManagedProcessorMBean;
056import org.apache.camel.api.management.mbean.ManagedRouteMBean;
057import org.apache.camel.model.ModelCamelContext;
058import org.apache.camel.model.ModelHelper;
059import org.apache.camel.model.RouteDefinition;
060import org.apache.camel.model.RoutesDefinition;
061import org.apache.camel.model.rest.RestDefinition;
062import org.apache.camel.model.rest.RestsDefinition;
063import org.apache.camel.spi.ManagementStrategy;
064import org.apache.camel.util.CamelContextHelper;
065import org.apache.camel.util.JsonSchemaHelper;
066import org.apache.camel.util.ObjectHelper;
067import org.apache.camel.util.XmlLineNumberParser;
068import org.slf4j.Logger;
069import org.slf4j.LoggerFactory;
070
071/**
072 * @version
073 */
074@ManagedResource(description = "Managed CamelContext")
075public class ManagedCamelContext extends ManagedPerformanceCounter implements TimerListener, ManagedCamelContextMBean {
076
077    private static final Logger LOG = LoggerFactory.getLogger(ManagedCamelContext.class);
078
079    private final ModelCamelContext context;
080    private final LoadTriplet load = new LoadTriplet();
081    private final String jmxDomain;
082
083    public ManagedCamelContext(ModelCamelContext context) {
084        this.context = context;
085        this.jmxDomain = context.getManagementStrategy().getManagementAgent().getMBeanObjectDomainName();
086    }
087
088    @Override
089    public void init(ManagementStrategy strategy) {
090        super.init(strategy);
091        boolean enabled = context.getManagementStrategy().getManagementAgent() != null && context.getManagementStrategy().getManagementAgent().getStatisticsLevel() != ManagementStatisticsLevel.Off;
092        setStatisticsEnabled(enabled);
093    }
094
095    public CamelContext getContext() {
096        return context;
097    }
098
099    public String getCamelId() {
100        return context.getName();
101    }
102
103    public String getManagementName() {
104        return context.getManagementName();
105    }
106
107    public String getCamelVersion() {
108        return context.getVersion();
109    }
110
111    public String getState() {
112        return context.getStatus().name();
113    }
114
115    public String getUptime() {
116        return context.getUptime();
117    }
118
119    public long getUptimeMillis() {
120        return context.getUptimeMillis();
121    }
122
123    public String getManagementStatisticsLevel() {
124        if (context.getManagementStrategy().getManagementAgent() != null) {
125            return context.getManagementStrategy().getManagementAgent().getStatisticsLevel().name();
126        } else {
127            return null;
128        }
129    }
130
131    public String getClassResolver() {
132        return context.getClassResolver().getClass().getName();
133    }
134
135    public String getPackageScanClassResolver() {
136        return context.getPackageScanClassResolver().getClass().getName();
137    }
138
139    public String getApplicationContextClassName() {
140        if (context.getApplicationContextClassLoader() != null) {
141            return context.getApplicationContextClassLoader().toString();
142        } else {
143            return null;
144        }
145    }
146
147    public Map<String, String> getProperties() {
148        if (context.getProperties().isEmpty()) {
149            return null;
150        }
151        return context.getProperties();
152    }
153
154    public String getProperty(String name) throws Exception {
155        return context.getProperty(name);
156    }
157
158    public void setProperty(String name, String value) throws Exception {
159        context.getProperties().put(name, value);
160    }
161
162    public Boolean getTracing() {
163        return context.isTracing();
164    }
165
166    public void setTracing(Boolean tracing) {
167        context.setTracing(tracing);
168    }
169
170    public Integer getInflightExchanges() {
171        return (int) super.getExchangesInflight();
172    }
173
174    public Integer getTotalRoutes() {
175        return context.getRoutes().size();
176    }
177
178    public Integer getStartedRoutes() {
179        int started = 0;
180        for (Route route : context.getRoutes()) {
181            if (context.getRouteStatus(route.getId()).isStarted()) {
182                started++;
183            }
184        }
185        return started;
186    }
187
188    public void setTimeout(long timeout) {
189        context.getShutdownStrategy().setTimeout(timeout);
190    }
191
192    public long getTimeout() {
193        return context.getShutdownStrategy().getTimeout();
194    }
195
196    public void setTimeUnit(TimeUnit timeUnit) {
197        context.getShutdownStrategy().setTimeUnit(timeUnit);
198    }
199
200    public TimeUnit getTimeUnit() {
201        return context.getShutdownStrategy().getTimeUnit();
202    }
203
204    public void setShutdownNowOnTimeout(boolean shutdownNowOnTimeout) {
205        context.getShutdownStrategy().setShutdownNowOnTimeout(shutdownNowOnTimeout);
206    }
207
208    public boolean isShutdownNowOnTimeout() {
209        return context.getShutdownStrategy().isShutdownNowOnTimeout();
210    }
211
212    public String getLoad01() {
213        double load1 = load.getLoad1();
214        if (Double.isNaN(load1)) {
215            // empty string if load statistics is disabled
216            return "";
217        } else {
218            return String.format("%.2f", load1);
219        }
220    }
221
222    public String getLoad05() {
223        double load5 = load.getLoad5();
224        if (Double.isNaN(load5)) {
225            // empty string if load statistics is disabled
226            return "";
227        } else {
228            return String.format("%.2f", load5);
229        }
230    }
231
232    public String getLoad15() {
233        double load15 = load.getLoad15();
234        if (Double.isNaN(load15)) {
235            // empty string if load statistics is disabled
236            return "";
237        } else {
238            return String.format("%.2f", load15);
239        }
240    }
241
242    public boolean isUseBreadcrumb() {
243        return context.isUseBreadcrumb();
244    }
245
246    public boolean isAllowUseOriginalMessage() {
247        return context.isAllowUseOriginalMessage();
248    }
249
250    public boolean isMessageHistory() {
251        return context.isMessageHistory() != null ? context.isMessageHistory() : false;
252    }
253
254    public boolean isUseMDCLogging() {
255        return context.isUseMDCLogging();
256    }
257
258    public void onTimer() {
259        load.update(getInflightExchanges());
260    }
261
262    public void start() throws Exception {
263        if (context.isSuspended()) {
264            context.resume();
265        } else {
266            context.start();
267        }
268    }
269
270    public void stop() throws Exception {
271        context.stop();
272    }
273
274    public void restart() throws Exception {
275        context.stop();
276        context.start();
277    }
278
279    public void suspend() throws Exception {
280        context.suspend();
281    }
282
283    public void resume() throws Exception {
284        if (context.isSuspended()) {
285            context.resume();
286        } else {
287            throw new IllegalStateException("CamelContext is not suspended");
288        }
289    }
290
291    public void startAllRoutes() throws Exception {
292        context.startAllRoutes();
293    }
294
295    public boolean canSendToEndpoint(String endpointUri) {
296        try {
297            Endpoint endpoint = context.getEndpoint(endpointUri);
298            if (endpoint != null) {
299                Producer producer = endpoint.createProducer();
300                return producer != null;
301            }
302        } catch (Exception e) {
303            // ignore
304        }
305
306        return false;
307    }
308
309    public void sendBody(String endpointUri, Object body) throws Exception {
310        ProducerTemplate template = context.createProducerTemplate();
311        try {
312            template.sendBody(endpointUri, body);
313        } finally {
314            template.stop();
315        }
316    }
317
318    public void sendStringBody(String endpointUri, String body) throws Exception {
319        sendBody(endpointUri, body);
320    }
321
322    public void sendBodyAndHeaders(String endpointUri, Object body, Map<String, Object> headers) throws Exception {
323        ProducerTemplate template = context.createProducerTemplate();
324        try {
325            template.sendBodyAndHeaders(endpointUri, body, headers);
326        } finally {
327            template.stop();
328        }
329    }
330
331    public Object requestBody(String endpointUri, Object body) throws Exception {
332        ProducerTemplate template = context.createProducerTemplate();
333        Object answer = null;
334        try {
335            answer = template.requestBody(endpointUri, body);
336        } finally {
337            template.stop();
338        }
339        return answer;
340    }
341
342    public Object requestStringBody(String endpointUri, String body) throws Exception {
343        return requestBody(endpointUri, body);
344    }
345
346    public Object requestBodyAndHeaders(String endpointUri, Object body, Map<String, Object> headers) throws Exception {
347        ProducerTemplate template = context.createProducerTemplate();
348        Object answer = null;
349        try {
350            answer = template.requestBodyAndHeaders(endpointUri, body, headers);
351        } finally {
352            template.stop();
353        }
354        return answer;
355    }
356
357    public String dumpRestsAsXml() throws Exception {
358        return dumpRestsAsXml(false);
359    }
360
361    @Override
362    public String dumpRestsAsXml(boolean resolvePlaceholders) throws Exception {
363        List<RestDefinition> rests = context.getRestDefinitions();
364        if (rests.isEmpty()) {
365            return null;
366        }
367
368        // use a routes definition to dump the rests
369        RestsDefinition def = new RestsDefinition();
370        def.setRests(rests);
371        String xml = ModelHelper.dumpModelAsXml(context, def);
372
373        // if resolving placeholders we parse the xml, and resolve the property placeholders during parsing
374        if (resolvePlaceholders) {
375            final AtomicBoolean changed = new AtomicBoolean();
376            InputStream is = new ByteArrayInputStream(xml.getBytes());
377            Document dom = XmlLineNumberParser.parseXml(is, new XmlLineNumberParser.XmlTextTransformer() {
378                @Override
379                public String transform(String text) {
380                    try {
381                        String after = getContext().resolvePropertyPlaceholders(text);
382                        if (!changed.get()) {
383                            changed.set(!text.equals(after));
384                        }
385                        return after;
386                    } catch (Exception e) {
387                        // ignore
388                        return text;
389                    }
390                }
391            });
392            // okay there were some property placeholder replaced so re-create the model
393            if (changed.get()) {
394                xml = context.getTypeConverter().mandatoryConvertTo(String.class, dom);
395                RestsDefinition copy = ModelHelper.createModelFromXml(context, xml, RestsDefinition.class);
396                xml = ModelHelper.dumpModelAsXml(context, copy);
397            }
398        }
399
400        return xml;
401    }
402
403    public String dumpRoutesAsXml() throws Exception {
404        return dumpRoutesAsXml(false);
405    }
406
407    @Override
408    public String dumpRoutesAsXml(boolean resolvePlaceholders) throws Exception {
409        List<RouteDefinition> routes = context.getRouteDefinitions();
410        if (routes.isEmpty()) {
411            return null;
412        }
413
414        // use a routes definition to dump the routes
415        RoutesDefinition def = new RoutesDefinition();
416        def.setRoutes(routes);
417        String xml = ModelHelper.dumpModelAsXml(context, def);
418
419        // if resolving placeholders we parse the xml, and resolve the property placeholders during parsing
420        if (resolvePlaceholders) {
421            final AtomicBoolean changed = new AtomicBoolean();
422            InputStream is = new ByteArrayInputStream(xml.getBytes());
423            Document dom = XmlLineNumberParser.parseXml(is, new XmlLineNumberParser.XmlTextTransformer() {
424                @Override
425                public String transform(String text) {
426                    try {
427                        String after = getContext().resolvePropertyPlaceholders(text);
428                        if (!changed.get()) {
429                            changed.set(!text.equals(after));
430                        }
431                        return after;
432                    } catch (Exception e) {
433                        // ignore
434                        return text;
435                    }
436                }
437            });
438            // okay there were some property placeholder replaced so re-create the model
439            if (changed.get()) {
440                xml = context.getTypeConverter().mandatoryConvertTo(String.class, dom);
441                RoutesDefinition copy = ModelHelper.createModelFromXml(context, xml, RoutesDefinition.class);
442                xml = ModelHelper.dumpModelAsXml(context, copy);
443            }
444        }
445
446        return xml;
447    }
448
449    public void addOrUpdateRoutesFromXml(String xml) throws Exception {
450        // do not decode so we function as before
451        addOrUpdateRoutesFromXml(xml, false);
452    }
453
454    public void addOrUpdateRoutesFromXml(String xml, boolean urlDecode) throws Exception {
455        // decode String as it may have been encoded, from its xml source
456        if (urlDecode) {
457            xml = URLDecoder.decode(xml, "UTF-8");
458        }
459
460        InputStream is = context.getTypeConverter().mandatoryConvertTo(InputStream.class, xml);
461        RoutesDefinition def = context.loadRoutesDefinition(is);
462        if (def == null) {
463            return;
464        }
465
466        try {
467            // add will remove existing route first
468            context.addRouteDefinitions(def.getRoutes());
469        } catch (Exception e) {
470            // log the error as warn as the management api may be invoked remotely over JMX which does not propagate such exception
471            String msg = "Error updating routes from xml: " + xml + " due: " + e.getMessage();
472            LOG.warn(msg, e);
473            throw e;
474        }
475    }
476
477    public String dumpRoutesStatsAsXml(boolean fullStats, boolean includeProcessors) throws Exception {
478        StringBuilder sb = new StringBuilder();
479        sb.append("<camelContextStat").append(String.format(" id=\"%s\" state=\"%s\"", getCamelId(), getState()));
480        // use substring as we only want the attributes
481        String stat = dumpStatsAsXml(fullStats);
482        sb.append(" exchangesInflight=\"").append(getInflightExchanges()).append("\"");
483        sb.append(" ").append(stat.substring(7, stat.length() - 2)).append(">\n");
484
485        MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer();
486        if (server != null) {
487            // gather all the routes for this CamelContext, which requires JMX
488            String prefix = getContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : "";
489            ObjectName query = ObjectName.getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=routes,*");
490            Set<ObjectName> routes = server.queryNames(query, null);
491
492            List<ManagedProcessorMBean> processors = new ArrayList<ManagedProcessorMBean>();
493            if (includeProcessors) {
494                // gather all the processors for this CamelContext, which requires JMX
495                query = ObjectName.getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=processors,*");
496                Set<ObjectName> names = server.queryNames(query, null);
497                for (ObjectName on : names) {
498                    ManagedProcessorMBean processor = context.getManagementStrategy().getManagementAgent().newProxyClient(on, ManagedProcessorMBean.class);
499                    processors.add(processor);
500                }
501            }
502            processors.sort(new OrderProcessorMBeans());
503
504            // loop the routes, and append the processor stats if needed
505            sb.append("  <routeStats>\n");
506            for (ObjectName on : routes) {
507                ManagedRouteMBean route = context.getManagementStrategy().getManagementAgent().newProxyClient(on, ManagedRouteMBean.class);
508                sb.append("    <routeStat").append(String.format(" id=\"%s\" state=\"%s\"", route.getRouteId(), route.getState()));
509                // use substring as we only want the attributes
510                stat = route.dumpStatsAsXml(fullStats);
511                sb.append(" exchangesInflight=\"").append(route.getExchangesInflight()).append("\"");
512                sb.append(" ").append(stat.substring(7, stat.length() - 2)).append(">\n");
513
514                // add processor details if needed
515                if (includeProcessors) {
516                    sb.append("      <processorStats>\n");
517                    for (ManagedProcessorMBean processor : processors) {
518                        // the processor must belong to this route
519                        if (route.getRouteId().equals(processor.getRouteId())) {
520                            sb.append("        <processorStat").append(String.format(" id=\"%s\" index=\"%s\" state=\"%s\"", processor.getProcessorId(), processor.getIndex(), processor.getState()));
521                            // use substring as we only want the attributes
522                            stat = processor.dumpStatsAsXml(fullStats);
523                            sb.append(" exchangesInflight=\"").append(processor.getExchangesInflight()).append("\"");
524                            sb.append(" ").append(stat.substring(7)).append("\n");
525                        }
526                    }
527                    sb.append("      </processorStats>\n");
528                }
529                sb.append("    </routeStat>\n");
530            }
531            sb.append("  </routeStats>\n");
532        }
533
534        sb.append("</camelContextStat>");
535        return sb.toString();
536    }
537
538    public String dumpRoutesCoverageAsXml() throws Exception {
539        StringBuilder sb = new StringBuilder();
540        sb.append("<camelContextRouteCoverage")
541                .append(String.format(" id=\"%s\" exchangesTotal=\"%s\" totalProcessingTime=\"%s\"", getCamelId(), getExchangesTotal(), getTotalProcessingTime()))
542                .append(">\n");
543
544        String xml = dumpRoutesAsXml();
545        if (xml != null) {
546            // use the coverage xml parser to dump the routes and enrich with coverage stats
547            Document dom = RouteCoverageXmlParser.parseXml(context, new ByteArrayInputStream(xml.getBytes()));
548            // convert dom back to xml
549            String converted = context.getTypeConverter().convertTo(String.class, dom);
550            sb.append(converted);
551        }
552
553        sb.append("\n</camelContextRouteCoverage>");
554        return sb.toString();
555    }
556
557    public boolean createEndpoint(String uri) throws Exception {
558        if (context.hasEndpoint(uri) != null) {
559            // endpoint already exists
560            return false;
561        }
562
563        Endpoint endpoint = context.getEndpoint(uri);
564        if (endpoint != null) {
565            // ensure endpoint is registered, as the management strategy could have been configured to not always
566            // register new endpoints in JMX, so we need to check if its registered, and if not register it manually
567            ObjectName on = context.getManagementStrategy().getManagementNamingStrategy().getObjectNameForEndpoint(endpoint);
568            if (on != null && !context.getManagementStrategy().getManagementAgent().isRegistered(on)) {
569                // register endpoint as mbean
570                Object me = context.getManagementStrategy().getManagementObjectStrategy().getManagedObjectForEndpoint(context, endpoint);
571                context.getManagementStrategy().getManagementAgent().register(me, on);
572            }
573            return true;
574        } else {
575            return false;
576        }
577    }
578
579    public int removeEndpoints(String pattern) throws Exception {
580        // endpoints is always removed from JMX if removed from context
581        Collection<Endpoint> removed = context.removeEndpoints(pattern);
582        return removed.size();
583    }
584
585    public Map<String, Properties> findEips() throws Exception {
586        return context.findEips();
587    }
588
589    public List<String> findEipNames() throws Exception {
590        Map<String, Properties> map = findEips();
591        return new ArrayList<String>(map.keySet());
592    }
593
594    public TabularData listEips() throws Exception {
595        try {
596            // find all EIPs
597            Map<String, Properties> eips = context.findEips();
598
599            TabularData answer = new TabularDataSupport(CamelOpenMBeanTypes.listEipsTabularType());
600
601            // gather EIP detail for each eip
602            for (Map.Entry<String, Properties> entry : eips.entrySet()) {
603                String name = entry.getKey();
604                String title = (String) entry.getValue().get("title");
605                String description = (String) entry.getValue().get("description");
606                String label = (String) entry.getValue().get("label");
607                String type = (String) entry.getValue().get("class");
608                String status = CamelContextHelper.isEipInUse(context, name) ? "in use" : "on classpath";
609                CompositeType ct = CamelOpenMBeanTypes.listEipsCompositeType();
610                CompositeData data = new CompositeDataSupport(ct, new String[]{"name", "title", "description", "label", "status", "type"},
611                        new Object[]{name, title, description, label, status, type});
612                answer.put(data);
613            }
614            return answer;
615        } catch (Exception e) {
616            throw ObjectHelper.wrapRuntimeCamelException(e);
617        }
618    }
619
620    public Map<String, Properties> findComponents() throws Exception {
621        Map<String, Properties> answer = context.findComponents();
622        for (Map.Entry<String, Properties> entry : answer.entrySet()) {
623            if (entry.getValue() != null) {
624                // remove component as its not serializable over JMX
625                entry.getValue().remove("component");
626                // .. and components which just list all the components in the JAR/bundle and that is verbose and not needed
627                entry.getValue().remove("components");
628            }
629        }
630        return answer;
631    }
632
633    public String getComponentDocumentation(String componentName) throws IOException {
634        return context.getComponentDocumentation(componentName);
635    }
636
637    public String createRouteStaticEndpointJson() {
638        return createRouteStaticEndpointJson(true);
639    }
640
641    public String createRouteStaticEndpointJson(boolean includeDynamic) {
642        return context.createRouteStaticEndpointJson(null, includeDynamic);
643    }
644
645    public List<String> findComponentNames() throws Exception {
646        Map<String, Properties> map = findComponents();
647        return new ArrayList<String>(map.keySet());
648    }
649
650    @Override
651    public TabularData listComponents() throws Exception {
652        try {
653            // find all components
654            Map<String, Properties> components = context.findComponents();
655
656            TabularData answer = new TabularDataSupport(CamelOpenMBeanTypes.listComponentsTabularType());
657
658            // gather component detail for each component
659            for (Map.Entry<String, Properties> entry : components.entrySet()) {
660                String name = entry.getKey();
661                String title = null;
662                String syntax = null;
663                String description = null;
664                String label = null;
665                String deprecated = null;
666                String secret = null;
667                String status = context.hasComponent(name) != null ? "in use" : "on classpath";
668                String type = (String) entry.getValue().get("class");
669                String groupId = null;
670                String artifactId = null;
671                String version = null;
672
673                // a component may have been given a different name, so resolve its default name by its java type
674                // as we can find the component json information from the default component name
675                String defaultName = context.resolveComponentDefaultName(type);
676                String target = defaultName != null ? defaultName : name;
677
678                // load component json data, and parse it to gather the component meta-data
679                String json = context.getComponentParameterJsonSchema(target);
680                List<Map<String, String>> rows = JsonSchemaHelper.parseJsonSchema("component", json, false);
681                for (Map<String, String> row : rows) {
682                    if (row.containsKey("title")) {
683                        title = row.get("title");
684                    } else if (row.containsKey("syntax")) {
685                        syntax = row.get("syntax");
686                    } else if (row.containsKey("description")) {
687                        description = row.get("description");
688                    } else if (row.containsKey("label")) {
689                        label = row.get("label");
690                    } else if (row.containsKey("deprecated")) {
691                        deprecated = row.get("deprecated");
692                    } else if (row.containsKey("secret")) {
693                        secret = row.get("secret");
694                    } else if (row.containsKey("javaType")) {
695                        type = row.get("javaType");
696                    } else if (row.containsKey("groupId")) {
697                        groupId = row.get("groupId");
698                    } else if (row.containsKey("artifactId")) {
699                        artifactId = row.get("artifactId");
700                    } else if (row.containsKey("version")) {
701                        version = row.get("version");
702                    }
703                }
704
705                CompositeType ct = CamelOpenMBeanTypes.listComponentsCompositeType();
706                CompositeData data = new CompositeDataSupport(ct,
707                        new String[]{"name", "title", "syntax", "description", "label", "deprecated", "secret", "status", "type", "groupId", "artifactId", "version"},
708                        new Object[]{name, title, syntax, description, label, deprecated, secret, status, type, groupId, artifactId, version});
709                answer.put(data);
710            }
711            return answer;
712        } catch (Exception e) {
713            throw ObjectHelper.wrapRuntimeCamelException(e);
714        }
715    }
716
717    public List<String> completeEndpointPath(String componentName, Map<String, Object> endpointParameters,
718                                             String completionText) throws Exception {
719        if (completionText == null) {
720            completionText = "";
721        }
722        Component component = context.getComponent(componentName, false);
723        if (component != null) {
724            ComponentConfiguration configuration = component.createComponentConfiguration();
725            configuration.setParameters(endpointParameters);
726            return configuration.completeEndpointPath(completionText);
727        } else {
728            return new ArrayList<String>();
729        }
730    }
731
732    public String componentParameterJsonSchema(String componentName) throws Exception {
733        // favor using pre generated schema if component has that
734        String json = context.getComponentParameterJsonSchema(componentName);
735        if (json == null) {
736            // okay this requires having the component on the classpath and being instantiated
737            Component component = context.getComponent(componentName);
738            if (component != null) {
739                ComponentConfiguration configuration = component.createComponentConfiguration();
740                json = configuration.createParameterJsonSchema();
741            }
742        }
743        return json;
744    }
745
746    public String dataFormatParameterJsonSchema(String dataFormatName) throws Exception {
747        return context.getDataFormatParameterJsonSchema(dataFormatName);
748    }
749
750    public String languageParameterJsonSchema(String languageName) throws Exception {
751        return context.getLanguageParameterJsonSchema(languageName);
752    }
753
754    public String eipParameterJsonSchema(String eipName) throws Exception {
755        return context.getEipParameterJsonSchema(eipName);
756    }
757
758    public String explainEipJson(String nameOrId, boolean includeAllOptions) {
759        return context.explainEipJson(nameOrId, includeAllOptions);
760    }
761
762    public String explainComponentJson(String componentName, boolean includeAllOptions) throws Exception {
763        return context.explainComponentJson(componentName, includeAllOptions);
764    }
765
766    public String explainEndpointJson(String uri, boolean includeAllOptions) throws Exception {
767        return context.explainEndpointJson(uri, includeAllOptions);
768    }
769
770    public void reset(boolean includeRoutes) throws Exception {
771        reset();
772
773        // and now reset all routes for this route
774        if (includeRoutes) {
775            MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer();
776            if (server != null) {
777                String prefix = getContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : "";
778                ObjectName query = ObjectName.getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=routes,*");
779                Set<ObjectName> names = server.queryNames(query, null);
780                for (ObjectName name : names) {
781                    server.invoke(name, "reset", new Object[]{true}, new String[]{"boolean"});
782                }
783            }
784        }
785    }
786
787    /**
788     * Used for sorting the processor mbeans accordingly to their index.
789     */
790    private static final class OrderProcessorMBeans implements Comparator<ManagedProcessorMBean> {
791
792        @Override
793        public int compare(ManagedProcessorMBean o1, ManagedProcessorMBean o2) {
794            return o1.getIndex().compareTo(o2.getIndex());
795        }
796    }
797
798}