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