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.util.ArrayList;
021import java.util.Collection;
022import java.util.Comparator;
023import java.util.List;
024import java.util.Map;
025import java.util.Set;
026import java.util.concurrent.TimeUnit;
027
028import javax.management.MBeanServer;
029import javax.management.ObjectName;
030
031import org.w3c.dom.Document;
032
033import org.apache.camel.CamelContext;
034import org.apache.camel.Endpoint;
035import org.apache.camel.Exchange;
036import org.apache.camel.ExtendedCamelContext;
037import org.apache.camel.ManagementStatisticsLevel;
038import org.apache.camel.Producer;
039import org.apache.camel.ProducerTemplate;
040import org.apache.camel.Route;
041import org.apache.camel.TimerListener;
042import org.apache.camel.api.management.ManagedResource;
043import org.apache.camel.api.management.mbean.ManagedCamelContextMBean;
044import org.apache.camel.api.management.mbean.ManagedProcessorMBean;
045import org.apache.camel.api.management.mbean.ManagedRouteMBean;
046import org.apache.camel.api.management.mbean.ManagedStepMBean;
047import org.apache.camel.model.Model;
048import org.apache.camel.model.ModelCamelContext;
049import org.apache.camel.model.RouteDefinition;
050import org.apache.camel.model.RouteTemplateDefinition;
051import org.apache.camel.model.RouteTemplatesDefinition;
052import org.apache.camel.model.RoutesDefinition;
053import org.apache.camel.model.rest.RestDefinition;
054import org.apache.camel.model.rest.RestsDefinition;
055import org.apache.camel.spi.ManagementStrategy;
056import org.apache.camel.spi.UnitOfWork;
057
058@ManagedResource(description = "Managed CamelContext")
059public class ManagedCamelContext extends ManagedPerformanceCounter implements TimerListener, ManagedCamelContextMBean {
060
061    private final CamelContext context;
062    private final LoadTriplet load = new LoadTriplet();
063    private final LoadThroughput thp = new LoadThroughput();
064    private final String jmxDomain;
065
066    public ManagedCamelContext(CamelContext context) {
067        this.context = context;
068        this.jmxDomain = context.getManagementStrategy().getManagementAgent().getMBeanObjectDomainName();
069    }
070
071    @Override
072    public void init(ManagementStrategy strategy) {
073        super.init(strategy);
074        boolean enabled = context.getManagementStrategy().getManagementAgent() != null
075                && context.getManagementStrategy().getManagementAgent().getStatisticsLevel() != ManagementStatisticsLevel.Off;
076        setStatisticsEnabled(enabled);
077    }
078
079    @Override
080    public void completedExchange(Exchange exchange, long time) {
081        // the camel-context mbean is triggered for every route mbean
082        // so we must only trigger on the root level, otherwise the context mbean
083        // total counter will be incorrect. For example if an exchange is routed via 3 routes
084        // we should only count this as 1 instead of 3.
085        UnitOfWork uow = exchange.getUnitOfWork();
086        if (uow != null) {
087            int level = uow.routeStackLevel();
088            if (level <= 1) {
089                super.completedExchange(exchange, time);
090            }
091        } else {
092            super.completedExchange(exchange, time);
093        }
094    }
095
096    @Override
097    public void failedExchange(Exchange exchange) {
098        // the camel-context mbean is triggered for every route mbean
099        // so we must only trigger on the root level, otherwise the context mbean
100        // total counter will be incorrect. For example if an exchange is routed via 3 routes
101        // we should only count this as 1 instead of 3.
102        UnitOfWork uow = exchange.getUnitOfWork();
103        if (uow != null) {
104            int level = uow.routeStackLevel();
105            if (level <= 1) {
106                super.failedExchange(exchange);
107            }
108        } else {
109            super.failedExchange(exchange);
110        }
111    }
112
113    @Override
114    public void processExchange(Exchange exchange, String type) {
115        // the camel-context mbean is triggered for every route mbean
116        // so we must only trigger on the root level, otherwise the context mbean
117        // total counter will be incorrect. For example if an exchange is routed via 3 routes
118        // we should only count this as 1 instead of 3.
119        UnitOfWork uow = exchange.getUnitOfWork();
120        if (uow != null) {
121            int level = uow.routeStackLevel();
122            if (level <= 1) {
123                super.processExchange(exchange, type);
124            }
125        } else {
126            super.processExchange(exchange, type);
127        }
128    }
129
130    public CamelContext getContext() {
131        return context;
132    }
133
134    @Override
135    public String getCamelId() {
136        return context.getName();
137    }
138
139    @Override
140    public String getCamelDescription() {
141        return context.getDescription();
142    }
143
144    @Override
145    public String getManagementName() {
146        return context.getManagementName();
147    }
148
149    @Override
150    public String getCamelVersion() {
151        return context.getVersion();
152    }
153
154    @Override
155    public String getState() {
156        return context.getStatus().name();
157    }
158
159    @Override
160    public String getUptime() {
161        return context.getUptime();
162    }
163
164    @Override
165    public long getUptimeMillis() {
166        return context.getUptimeMillis();
167    }
168
169    @Override
170    public String getManagementStatisticsLevel() {
171        if (context.getManagementStrategy().getManagementAgent() != null) {
172            return context.getManagementStrategy().getManagementAgent().getStatisticsLevel().name();
173        } else {
174            return null;
175        }
176    }
177
178    @Override
179    public String getClassResolver() {
180        return context.getClassResolver().getClass().getName();
181    }
182
183    @Override
184    public String getPackageScanClassResolver() {
185        return context.adapt(ExtendedCamelContext.class).getPackageScanClassResolver().getClass().getName();
186    }
187
188    @Override
189    public String getApplicationContextClassName() {
190        if (context.getApplicationContextClassLoader() != null) {
191            return context.getApplicationContextClassLoader().getClass().getName();
192        } else {
193            return null;
194        }
195    }
196
197    @Override
198    public String getHeadersMapFactoryClassName() {
199        return context.adapt(ExtendedCamelContext.class).getHeadersMapFactory().getClass().getName();
200    }
201
202    @Override
203    public Map<String, String> getGlobalOptions() {
204        if (context.getGlobalOptions().isEmpty()) {
205            return null;
206        }
207        return context.getGlobalOptions();
208    }
209
210    @Override
211    public String getGlobalOption(String key) throws Exception {
212        return context.getGlobalOption(key);
213    }
214
215    @Override
216    public void setGlobalOption(String key, String value) throws Exception {
217        context.getGlobalOptions().put(key, value);
218    }
219
220    @Override
221    public Boolean getTracing() {
222        return context.isTracing();
223    }
224
225    @Override
226    public void setTracing(Boolean tracing) {
227        context.setTracing(tracing);
228    }
229
230    public Integer getInflightExchanges() {
231        return (int) super.getExchangesInflight();
232    }
233
234    @Override
235    public Integer getTotalRoutes() {
236        return context.getRoutesSize();
237    }
238
239    @Override
240    public Integer getStartedRoutes() {
241        int started = 0;
242        for (Route route : context.getRoutes()) {
243            if (context.getRouteController().getRouteStatus(route.getId()).isStarted()) {
244                started++;
245            }
246        }
247        return started;
248    }
249
250    @Override
251    public void setTimeout(long timeout) {
252        context.getShutdownStrategy().setTimeout(timeout);
253    }
254
255    @Override
256    public long getTimeout() {
257        return context.getShutdownStrategy().getTimeout();
258    }
259
260    @Override
261    public void setTimeUnit(TimeUnit timeUnit) {
262        context.getShutdownStrategy().setTimeUnit(timeUnit);
263    }
264
265    @Override
266    public TimeUnit getTimeUnit() {
267        return context.getShutdownStrategy().getTimeUnit();
268    }
269
270    @Override
271    public void setShutdownNowOnTimeout(boolean shutdownNowOnTimeout) {
272        context.getShutdownStrategy().setShutdownNowOnTimeout(shutdownNowOnTimeout);
273    }
274
275    @Override
276    public boolean isShutdownNowOnTimeout() {
277        return context.getShutdownStrategy().isShutdownNowOnTimeout();
278    }
279
280    @Override
281    public String getLoad01() {
282        double load1 = load.getLoad1();
283        if (Double.isNaN(load1)) {
284            // empty string if load statistics is disabled
285            return "";
286        } else {
287            return String.format("%.2f", load1);
288        }
289    }
290
291    @Override
292    public String getLoad05() {
293        double load5 = load.getLoad5();
294        if (Double.isNaN(load5)) {
295            // empty string if load statistics is disabled
296            return "";
297        } else {
298            return String.format("%.2f", load5);
299        }
300    }
301
302    @Override
303    public String getLoad15() {
304        double load15 = load.getLoad15();
305        if (Double.isNaN(load15)) {
306            // empty string if load statistics is disabled
307            return "";
308        } else {
309            return String.format("%.2f", load15);
310        }
311    }
312
313    @Override
314    public String getThroughput() {
315        double d = thp.getThroughput();
316        if (Double.isNaN(d)) {
317            // empty string if load statistics is disabled
318            return "";
319        } else {
320            return String.format("%.2f", d);
321        }
322    }
323
324    @Override
325    public boolean isUseBreadcrumb() {
326        return context.isUseBreadcrumb();
327    }
328
329    @Override
330    public boolean isAllowUseOriginalMessage() {
331        return context.isAllowUseOriginalMessage();
332    }
333
334    @Override
335    public boolean isMessageHistory() {
336        return context.isMessageHistory() != null ? context.isMessageHistory() : false;
337    }
338
339    @Override
340    public boolean isLogMask() {
341        return context.isLogMask() != null ? context.isLogMask() : false;
342    }
343
344    @Override
345    public boolean isUseMDCLogging() {
346        return context.isUseMDCLogging();
347    }
348
349    @Override
350    public boolean isUseDataType() {
351        return context.isUseDataType();
352    }
353
354    @Override
355    public void onTimer() {
356        load.update(getInflightExchanges());
357        thp.update(getExchangesTotal());
358    }
359
360    @Override
361    public void start() throws Exception {
362        if (context.isSuspended()) {
363            context.resume();
364        } else {
365            context.start();
366        }
367    }
368
369    @Override
370    public void stop() throws Exception {
371        context.stop();
372    }
373
374    @Override
375    public void restart() throws Exception {
376        context.stop();
377        context.start();
378    }
379
380    @Override
381    public void suspend() throws Exception {
382        context.suspend();
383    }
384
385    @Override
386    public void resume() throws Exception {
387        if (context.isSuspended()) {
388            context.resume();
389        } else {
390            throw new IllegalStateException("CamelContext is not suspended");
391        }
392    }
393
394    @Override
395    public void startAllRoutes() throws Exception {
396        context.getRouteController().startAllRoutes();
397    }
398
399    @Override
400    public boolean canSendToEndpoint(String endpointUri) {
401        try {
402            Endpoint endpoint = context.getEndpoint(endpointUri);
403            if (endpoint != null) {
404                try (Producer producer = endpoint.createProducer()) {
405                    return producer != null;
406                }
407            }
408        } catch (Exception e) {
409            // ignore
410        }
411
412        return false;
413    }
414
415    @Override
416    public void sendBody(String endpointUri, Object body) throws Exception {
417        try (ProducerTemplate template = context.createProducerTemplate()) {
418            template.sendBody(endpointUri, body);
419        }
420    }
421
422    @Override
423    public void sendStringBody(String endpointUri, String body) throws Exception {
424        sendBody(endpointUri, body);
425    }
426
427    @Override
428    public void sendBodyAndHeaders(String endpointUri, Object body, Map<String, Object> headers) throws Exception {
429        try (ProducerTemplate template = context.createProducerTemplate()) {
430            template.sendBodyAndHeaders(endpointUri, body, headers);
431        }
432    }
433
434    @Override
435    public Object requestBody(String endpointUri, Object body) throws Exception {
436        try (ProducerTemplate template = context.createProducerTemplate()) {
437            return template.requestBody(endpointUri, body);
438        }
439    }
440
441    @Override
442    public Object requestStringBody(String endpointUri, String body) throws Exception {
443        return requestBody(endpointUri, body);
444    }
445
446    @Override
447    public Object requestBodyAndHeaders(String endpointUri, Object body, Map<String, Object> headers) throws Exception {
448        try (ProducerTemplate template = context.createProducerTemplate()) {
449            return template.requestBodyAndHeaders(endpointUri, body, headers);
450        }
451
452    }
453
454    @Override
455    public String dumpRestsAsXml() throws Exception {
456        return dumpRestsAsXml(false);
457    }
458
459    @Override
460    public String dumpRestsAsXml(boolean resolvePlaceholders) throws Exception {
461        List<RestDefinition> rests = context.getExtension(Model.class).getRestDefinitions();
462        if (rests.isEmpty()) {
463            return null;
464        }
465
466        RestsDefinition def = new RestsDefinition();
467        def.setRests(rests);
468
469        ExtendedCamelContext ecc = context.adapt(ExtendedCamelContext.class);
470        return ecc.getModelToXMLDumper().dumpModelAsXml(context, def, resolvePlaceholders, false);
471    }
472
473    @Override
474    public String dumpRoutesAsXml() throws Exception {
475        return dumpRoutesAsXml(false, false);
476    }
477
478    @Override
479    public String dumpRoutesAsXml(boolean resolvePlaceholders) throws Exception {
480        return dumpRoutesAsXml(resolvePlaceholders, false);
481    }
482
483    @Override
484    public String dumpRoutesAsXml(boolean resolvePlaceholders, boolean resolveDelegateEndpoints) throws Exception {
485        List<RouteDefinition> routes = context.getExtension(Model.class).getRouteDefinitions();
486        if (routes.isEmpty()) {
487            return null;
488        }
489
490        // use routes definition to dump the routes
491        RoutesDefinition def = new RoutesDefinition();
492        def.setRoutes(routes);
493
494        ExtendedCamelContext ecc = context.adapt(ExtendedCamelContext.class);
495        return ecc.getModelToXMLDumper().dumpModelAsXml(context, def, resolvePlaceholders, resolveDelegateEndpoints);
496    }
497
498    @Override
499    public String dumpRouteTemplatesAsXml() throws Exception {
500        List<RouteTemplateDefinition> templates = context.getExtension(Model.class).getRouteTemplateDefinitions();
501        if (templates.isEmpty()) {
502            return null;
503        }
504
505        // use a route templates definition to dump the templates
506        RouteTemplatesDefinition def = new RouteTemplatesDefinition();
507        def.setRouteTemplates(templates);
508
509        ExtendedCamelContext ecc = context.adapt(ExtendedCamelContext.class);
510        return ecc.getModelToXMLDumper().dumpModelAsXml(context, def);
511    }
512
513    @Override
514    public String dumpRoutesStatsAsXml(boolean fullStats, boolean includeProcessors) throws Exception {
515        StringBuilder sb = new StringBuilder();
516        sb.append("<camelContextStat").append(String.format(" id=\"%s\" state=\"%s\"", getCamelId(), getState()));
517        // use substring as we only want the attributes
518        String stat = dumpStatsAsXml(fullStats);
519        sb.append(" exchangesInflight=\"").append(getInflightExchanges()).append("\"");
520        sb.append(" ").append(stat, 7, stat.length() - 2).append(">\n");
521
522        MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer();
523        if (server != null) {
524            // gather all the routes for this CamelContext, which requires JMX
525            String prefix = getContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : "";
526            ObjectName query = ObjectName
527                    .getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=routes,*");
528            Set<ObjectName> routes = server.queryNames(query, null);
529
530            List<ManagedProcessorMBean> processors = new ArrayList<>();
531            if (includeProcessors) {
532                // gather all the processors for this CamelContext, which requires JMX
533                query = ObjectName.getInstance(
534                        jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=processors,*");
535                Set<ObjectName> names = server.queryNames(query, null);
536                for (ObjectName on : names) {
537                    ManagedProcessorMBean processor = context.getManagementStrategy().getManagementAgent().newProxyClient(on,
538                            ManagedProcessorMBean.class);
539                    processors.add(processor);
540                }
541            }
542            processors.sort(new OrderProcessorMBeans());
543
544            // loop the routes, and append the processor stats if needed
545            sb.append("  <routeStats>\n");
546            for (ObjectName on : routes) {
547                ManagedRouteMBean route
548                        = context.getManagementStrategy().getManagementAgent().newProxyClient(on, ManagedRouteMBean.class);
549                sb.append("    <routeStat")
550                        .append(String.format(" id=\"%s\" state=\"%s\"", route.getRouteId(), route.getState()));
551                if (route.getSourceLocation() != null) {
552                    sb.append(String.format(" sourceLocation=\"%s\"", route.getSourceLocation()));
553                }
554
555                // use substring as we only want the attributes
556                stat = route.dumpStatsAsXml(fullStats);
557                sb.append(" exchangesInflight=\"").append(route.getExchangesInflight()).append("\"");
558                sb.append(" ").append(stat, 7, stat.length() - 2).append(">\n");
559
560                // add processor details if needed
561                if (includeProcessors) {
562                    sb.append("      <processorStats>\n");
563                    for (ManagedProcessorMBean processor : processors) {
564                        int line = processor.getSourceLineNumber() != null ? processor.getSourceLineNumber() : -1;
565                        // the processor must belong to this route
566                        if (route.getRouteId().equals(processor.getRouteId())) {
567                            sb.append("        <processorStat")
568                                    .append(String.format(" id=\"%s\" index=\"%s\" state=\"%s\" sourceLineNumber=\"%s\"",
569                                            processor.getProcessorId(), processor.getIndex(), processor.getState(), line));
570                            // use substring as we only want the attributes
571                            stat = processor.dumpStatsAsXml(fullStats);
572                            sb.append(" exchangesInflight=\"").append(processor.getExchangesInflight()).append("\"");
573                            sb.append(" ").append(stat, 7, stat.length()).append("\n");
574                        }
575                    }
576                    sb.append("      </processorStats>\n");
577                }
578                sb.append("    </routeStat>\n");
579            }
580            sb.append("  </routeStats>\n");
581        }
582
583        sb.append("</camelContextStat>");
584        return sb.toString();
585    }
586
587    @Override
588    public String dumpStepStatsAsXml(boolean fullStats) throws Exception {
589        StringBuilder sb = new StringBuilder();
590        sb.append("<camelContextStat").append(String.format(" id=\"%s\" state=\"%s\"", getCamelId(), getState()));
591        // use substring as we only want the attributes
592        String stat = dumpStatsAsXml(fullStats);
593        sb.append(" exchangesInflight=\"").append(getInflightExchanges()).append("\"");
594        sb.append(" ").append(stat, 7, stat.length() - 2).append(">\n");
595
596        MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer();
597        if (server != null) {
598            // gather all the routes for this CamelContext, which requires JMX
599            String prefix = getContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : "";
600            ObjectName query = ObjectName
601                    .getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=routes,*");
602            Set<ObjectName> routes = server.queryNames(query, null);
603
604            List<ManagedProcessorMBean> steps = new ArrayList<>();
605            // gather all the steps for this CamelContext, which requires JMX
606            query = ObjectName
607                    .getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=steps,*");
608            Set<ObjectName> names = server.queryNames(query, null);
609            for (ObjectName on : names) {
610                ManagedStepMBean step
611                        = context.getManagementStrategy().getManagementAgent().newProxyClient(on, ManagedStepMBean.class);
612                steps.add(step);
613            }
614            steps.sort(new OrderProcessorMBeans());
615
616            // loop the routes, and append the processor stats if needed
617            sb.append("  <routeStats>\n");
618            for (ObjectName on : routes) {
619                ManagedRouteMBean route
620                        = context.getManagementStrategy().getManagementAgent().newProxyClient(on, ManagedRouteMBean.class);
621                sb.append("    <routeStat")
622                        .append(String.format(" id=\"%s\" state=\"%s\"", route.getRouteId(), route.getState()));
623                if (route.getSourceLocation() != null) {
624                    sb.append(String.format(" sourceLocation=\"%s\"", route.getSourceLocation()));
625                }
626
627                // use substring as we only want the attributes
628                stat = route.dumpStatsAsXml(fullStats);
629                sb.append(" exchangesInflight=\"").append(route.getExchangesInflight()).append("\"");
630                sb.append(" ").append(stat, 7, stat.length() - 2).append(">\n");
631
632                // add steps details if needed
633                sb.append("      <stepStats>\n");
634                for (ManagedProcessorMBean step : steps) {
635                    // the step must belong to this route
636                    if (route.getRouteId().equals(step.getRouteId())) {
637                        int line = step.getSourceLineNumber() != null ? step.getSourceLineNumber() : -1;
638                        sb.append("        <stepStat")
639                                .append(String.format(" id=\"%s\" index=\"%s\" state=\"%s\" sourceLineNumber=\"%s\"",
640                                        step.getProcessorId(), step.getIndex(), step.getState(), line));
641                        // use substring as we only want the attributes
642                        stat = step.dumpStatsAsXml(fullStats);
643                        sb.append(" exchangesInflight=\"").append(step.getExchangesInflight()).append("\"");
644                        sb.append(" ").append(stat, 7, stat.length()).append("\n");
645                    }
646                    sb.append("      </stepStats>\n");
647                }
648                sb.append("    </stepStat>\n");
649            }
650            sb.append("  </routeStats>\n");
651        }
652
653        sb.append("</camelContextStat>");
654        return sb.toString();
655    }
656
657    @Override
658    public String dumpRoutesCoverageAsXml() throws Exception {
659        StringBuilder sb = new StringBuilder();
660        sb.append("<camelContextRouteCoverage")
661                .append(String.format(" id=\"%s\" exchangesTotal=\"%s\" totalProcessingTime=\"%s\"", getCamelId(),
662                        getExchangesTotal(), getTotalProcessingTime()))
663                .append(">\n");
664
665        String xml = dumpRoutesAsXml();
666        if (xml != null) {
667            // use the coverage xml parser to dump the routes and enrich with coverage stats
668            Document dom = RouteCoverageXmlParser.parseXml(context, new ByteArrayInputStream(xml.getBytes()));
669            // convert dom back to xml
670            String converted = context.getTypeConverter().convertTo(String.class, dom);
671            sb.append(converted);
672        }
673
674        sb.append("\n</camelContextRouteCoverage>");
675        return sb.toString();
676    }
677
678    @Override
679    @Deprecated
680    public String dumpRoutesSourceLocationsAsXml() throws Exception {
681        StringBuilder sb = new StringBuilder();
682        sb.append("<routeLocations>");
683
684        MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer();
685        if (server != null) {
686            // gather all the routes for this CamelContext, which requires JMX
687            List<ManagedRouteMBean> routes = new ArrayList<>();
688            String prefix = getContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : "";
689            ObjectName query = ObjectName
690                    .getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=routes,*");
691            Set<ObjectName> names = server.queryNames(query, null);
692            for (ObjectName on : names) {
693                ManagedRouteMBean route
694                        = context.getManagementStrategy().getManagementAgent().newProxyClient(on, ManagedRouteMBean.class);
695                routes.add(route);
696            }
697            routes.sort(new RouteMBeans());
698
699            List<ManagedProcessorMBean> processors = new ArrayList<>();
700            // gather all the processors for this CamelContext, which requires JMX
701            query = ObjectName
702                    .getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=processors,*");
703            names = server.queryNames(query, null);
704            for (ObjectName on : names) {
705                ManagedProcessorMBean processor
706                        = context.getManagementStrategy().getManagementAgent().newProxyClient(on, ManagedProcessorMBean.class);
707                processors.add(processor);
708            }
709            processors.sort(new OrderProcessorMBeans());
710
711            // loop the routes, and append the node ids (via processor)
712            for (ManagedRouteMBean route : routes) {
713                // grab route consumer
714                RouteDefinition rd = context.adapt(ModelCamelContext.class).getRouteDefinition(route.getRouteId());
715                if (rd != null) {
716                    String id = rd.getRouteId();
717                    int line = rd.getInput().getLineNumber();
718                    String location
719                            = rd.getInput().getLocation() != null ? rd.getInput().getLocation() : route.getSourceLocation();
720                    if (location == null) {
721                        location = "";
722                    }
723                    sb.append("\n    <routeLocation")
724                            .append(String.format(
725                                    " routeId=\"%s\" id=\"%s\" index=\"%s\" sourceLocation=\"%s\" sourceLineNumber=\"%s\"/>",
726                                    route.getRouteId(), id, 0, location, line));
727                }
728                for (ManagedProcessorMBean processor : processors) {
729                    // the step must belong to this route
730                    if (route.getRouteId().equals(processor.getRouteId())) {
731                        int line = processor.getSourceLineNumber() != null ? processor.getSourceLineNumber() : -1;
732                        String location = processor.getSourceLocation();
733                        if (location == null) {
734                            location = "";
735                        }
736                        sb.append("\n    <routeLocation")
737                                .append(String.format(
738                                        " routeId=\"%s\" id=\"%s\" index=\"%s\" sourceLocation=\"%s\" sourceLineNumber=\"%s\"/>",
739                                        route.getRouteId(), processor.getProcessorId(), processor.getIndex(), location, line));
740                    }
741                }
742            }
743        }
744        sb.append("\n</routeLocations>");
745        return sb.toString();
746    }
747
748    @Override
749    public boolean createEndpoint(String uri) throws Exception {
750        if (context.hasEndpoint(uri) != null) {
751            // endpoint already exists
752            return false;
753        }
754
755        Endpoint endpoint = context.getEndpoint(uri);
756        if (endpoint != null) {
757            // ensure endpoint is registered, as the management strategy could have been configured to not always
758            // register new endpoints in JMX, so we need to check if its registered, and if not register it manually
759            ObjectName on
760                    = context.getManagementStrategy().getManagementObjectNameStrategy().getObjectNameForEndpoint(endpoint);
761            if (on != null && !context.getManagementStrategy().getManagementAgent().isRegistered(on)) {
762                // register endpoint as mbean
763                Object me = context.getManagementStrategy().getManagementObjectStrategy().getManagedObjectForEndpoint(context,
764                        endpoint);
765                context.getManagementStrategy().getManagementAgent().register(me, on);
766            }
767            return true;
768        } else {
769            return false;
770        }
771    }
772
773    @Override
774    public int removeEndpoints(String pattern) throws Exception {
775        // endpoints is always removed from JMX if removed from context
776        Collection<Endpoint> removed = context.removeEndpoints(pattern);
777        return removed.size();
778    }
779
780    @Override
781    public void reset(boolean includeRoutes) throws Exception {
782        reset();
783        load.reset();
784        thp.reset();
785
786        // and now reset all routes for this route
787        if (includeRoutes) {
788            MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer();
789            if (server != null) {
790                String prefix = getContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : "";
791                ObjectName query = ObjectName
792                        .getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=routes,*");
793                Set<ObjectName> names = server.queryNames(query, null);
794                for (ObjectName name : names) {
795                    server.invoke(name, "reset", new Object[] { true }, new String[] { "boolean" });
796                }
797            }
798        }
799    }
800
801    @Override
802    public Set<String> componentNames() throws Exception {
803        return context.getComponentNames();
804    }
805
806    @Override
807    public Set<String> languageNames() throws Exception {
808        return context.getLanguageNames();
809    }
810
811    @Override
812    public Set<String> dataFormatNames() throws Exception {
813        return context.getDataFormatNames();
814    }
815
816    /**
817     * Used for sorting the processor mbeans accordingly to their index.
818     */
819    private static final class OrderProcessorMBeans implements Comparator<ManagedProcessorMBean> {
820
821        @Override
822        public int compare(ManagedProcessorMBean o1, ManagedProcessorMBean o2) {
823            return o1.getIndex().compareTo(o2.getIndex());
824        }
825    }
826
827    /**
828     * Used for sorting the routes mbeans accordingly to their ids.
829     */
830    private static final class RouteMBeans implements Comparator<ManagedRouteMBean> {
831
832        @Override
833        public int compare(ManagedRouteMBean o1, ManagedRouteMBean o2) {
834            return o1.getRouteId().compareToIgnoreCase(o2.getRouteId());
835        }
836    }
837
838}