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.Serializable; 020import java.util.ArrayList; 021import java.util.Collection; 022import java.util.Collections; 023import java.util.Comparator; 024import java.util.HashMap; 025import java.util.List; 026import java.util.Map; 027import java.util.Set; 028import java.util.concurrent.RejectedExecutionException; 029import java.util.concurrent.TimeUnit; 030 031import javax.management.AttributeValueExp; 032import javax.management.MBeanServer; 033import javax.management.ObjectName; 034import javax.management.Query; 035import javax.management.QueryExp; 036import javax.management.StringValueExp; 037import javax.management.openmbean.CompositeData; 038import javax.management.openmbean.CompositeDataSupport; 039import javax.management.openmbean.CompositeType; 040import javax.management.openmbean.TabularData; 041import javax.management.openmbean.TabularDataSupport; 042 043import org.apache.camel.CamelContext; 044import org.apache.camel.ExtendedCamelContext; 045import org.apache.camel.ManagementStatisticsLevel; 046import org.apache.camel.Route; 047import org.apache.camel.RuntimeCamelException; 048import org.apache.camel.ServiceStatus; 049import org.apache.camel.TimerListener; 050import org.apache.camel.api.management.ManagedResource; 051import org.apache.camel.api.management.mbean.CamelOpenMBeanTypes; 052import org.apache.camel.api.management.mbean.ManagedProcessorMBean; 053import org.apache.camel.api.management.mbean.ManagedRouteMBean; 054import org.apache.camel.api.management.mbean.ManagedStepMBean; 055import org.apache.camel.api.management.mbean.RouteError; 056import org.apache.camel.model.Model; 057import org.apache.camel.model.ModelCamelContext; 058import org.apache.camel.model.RouteDefinition; 059import org.apache.camel.spi.InflightRepository; 060import org.apache.camel.spi.ManagementStrategy; 061import org.apache.camel.spi.RoutePolicy; 062import org.apache.camel.util.ObjectHelper; 063import org.slf4j.Logger; 064import org.slf4j.LoggerFactory; 065 066@ManagedResource(description = "Managed Route") 067public class ManagedRoute extends ManagedPerformanceCounter implements TimerListener, ManagedRouteMBean { 068 069 public static final String VALUE_UNKNOWN = "Unknown"; 070 071 private static final Logger LOG = LoggerFactory.getLogger(ManagedRoute.class); 072 073 protected final Route route; 074 protected final String description; 075 protected final String configurationId; 076 protected final String sourceLocation; 077 protected final String sourceLocationShort; 078 protected final CamelContext context; 079 private final LoadTriplet load = new LoadTriplet(); 080 private final String jmxDomain; 081 082 public ManagedRoute(CamelContext context, Route route) { 083 this.route = route; 084 this.context = context; 085 this.description = route.getDescription(); 086 this.configurationId = route.getConfigurationId(); 087 this.sourceLocation = route.getSourceLocation(); 088 this.sourceLocationShort = route.getSourceLocationShort(); 089 this.jmxDomain = context.getManagementStrategy().getManagementAgent().getMBeanObjectDomainName(); 090 } 091 092 @Override 093 public void init(ManagementStrategy strategy) { 094 super.init(strategy); 095 boolean enabled 096 = context.getManagementStrategy().getManagementAgent().getStatisticsLevel() != ManagementStatisticsLevel.Off; 097 setStatisticsEnabled(enabled); 098 } 099 100 public Route getRoute() { 101 return route; 102 } 103 104 public CamelContext getContext() { 105 return context; 106 } 107 108 @Override 109 public String getRouteId() { 110 String id = route.getId(); 111 if (id == null) { 112 id = VALUE_UNKNOWN; 113 } 114 return id; 115 } 116 117 @Override 118 public String getRouteGroup() { 119 return route.getGroup(); 120 } 121 122 @Override 123 public TabularData getRouteProperties() { 124 try { 125 final Map<String, Object> properties = route.getProperties(); 126 final TabularData answer = new TabularDataSupport(CamelOpenMBeanTypes.camelRoutePropertiesTabularType()); 127 final CompositeType ct = CamelOpenMBeanTypes.camelRoutePropertiesCompositeType(); 128 129 // gather route properties 130 for (Map.Entry<String, Object> entry : properties.entrySet()) { 131 final String key = entry.getKey(); 132 final String val = context.getTypeConverter().convertTo(String.class, entry.getValue()); 133 134 CompositeData data = new CompositeDataSupport( 135 ct, 136 new String[] { "key", "value" }, 137 new Object[] { key, val }); 138 139 answer.put(data); 140 } 141 return answer; 142 } catch (Exception e) { 143 throw RuntimeCamelException.wrapRuntimeCamelException(e); 144 } 145 } 146 147 @Override 148 public String getDescription() { 149 return description; 150 } 151 152 @Override 153 public String getSourceLocation() { 154 return sourceLocation; 155 } 156 157 @Override 158 public String getSourceLocationShort() { 159 return null; 160 } 161 162 @Override 163 public String getRouteConfigurationId() { 164 return configurationId; 165 } 166 167 @Override 168 public String getEndpointUri() { 169 if (route.getEndpoint() != null) { 170 return route.getEndpoint().getEndpointUri(); 171 } 172 return VALUE_UNKNOWN; 173 } 174 175 @Override 176 public String getState() { 177 // must use String type to be sure remote JMX can read the attribute without requiring Camel classes. 178 ServiceStatus status = context.getRouteController().getRouteStatus(route.getId()); 179 // if no status exists then its stopped 180 if (status == null) { 181 status = ServiceStatus.Stopped; 182 } 183 return status.name(); 184 } 185 186 @Override 187 public String getUptime() { 188 return route.getUptime(); 189 } 190 191 @Override 192 public long getUptimeMillis() { 193 return route.getUptimeMillis(); 194 } 195 196 @Override 197 public String getCamelId() { 198 return context.getName(); 199 } 200 201 @Override 202 public String getCamelManagementName() { 203 return context.getManagementName(); 204 } 205 206 @Override 207 public Boolean getTracing() { 208 return route.isTracing(); 209 } 210 211 @Override 212 public void setTracing(Boolean tracing) { 213 route.setTracing(tracing); 214 } 215 216 @Override 217 public Boolean getMessageHistory() { 218 return route.isMessageHistory(); 219 } 220 221 @Override 222 public Boolean getLogMask() { 223 return route.isLogMask(); 224 } 225 226 @Override 227 public String getRoutePolicyList() { 228 List<RoutePolicy> policyList = route.getRoutePolicyList(); 229 230 if (policyList == null || policyList.isEmpty()) { 231 // return an empty string to have it displayed nicely in JMX consoles 232 return ""; 233 } 234 235 StringBuilder sb = new StringBuilder(); 236 for (int i = 0; i < policyList.size(); i++) { 237 RoutePolicy policy = policyList.get(i); 238 sb.append(policy.getClass().getSimpleName()); 239 sb.append("(").append(ObjectHelper.getIdentityHashCode(policy)).append(")"); 240 if (i < policyList.size() - 1) { 241 sb.append(", "); 242 } 243 } 244 return sb.toString(); 245 } 246 247 @Override 248 public String getLoad01() { 249 double load1 = load.getLoad1(); 250 if (Double.isNaN(load1)) { 251 // empty string if load statistics is disabled 252 return ""; 253 } else { 254 return String.format("%.2f", load1); 255 } 256 } 257 258 @Override 259 public String getLoad05() { 260 double load5 = load.getLoad5(); 261 if (Double.isNaN(load5)) { 262 // empty string if load statistics is disabled 263 return ""; 264 } else { 265 return String.format("%.2f", load5); 266 } 267 } 268 269 @Override 270 public String getLoad15() { 271 double load15 = load.getLoad15(); 272 if (Double.isNaN(load15)) { 273 // empty string if load statistics is disabled 274 return ""; 275 } else { 276 return String.format("%.2f", load15); 277 } 278 } 279 280 @Override 281 public void onTimer() { 282 load.update(getInflightExchanges()); 283 } 284 285 @Override 286 public void start() throws Exception { 287 if (!context.getStatus().isStarted()) { 288 throw new IllegalArgumentException("CamelContext is not started"); 289 } 290 context.getRouteController().startRoute(getRouteId()); 291 } 292 293 @Override 294 public void stop() throws Exception { 295 if (!context.getStatus().isStarted()) { 296 throw new IllegalArgumentException("CamelContext is not started"); 297 } 298 context.getRouteController().stopRoute(getRouteId()); 299 } 300 301 @Override 302 public void stopAndFail() throws Exception { 303 if (!context.getStatus().isStarted()) { 304 throw new IllegalArgumentException("CamelContext is not started"); 305 } 306 Throwable cause = new RejectedExecutionException("Route " + getRouteId() + " is forced stopped and marked as failed"); 307 context.getRouteController().stopRoute(getRouteId(), cause); 308 } 309 310 @Override 311 public void stop(long timeout) throws Exception { 312 if (!context.getStatus().isStarted()) { 313 throw new IllegalArgumentException("CamelContext is not started"); 314 } 315 context.getRouteController().stopRoute(getRouteId(), timeout, TimeUnit.SECONDS); 316 } 317 318 @Override 319 public boolean stop(Long timeout, Boolean abortAfterTimeout) throws Exception { 320 if (!context.getStatus().isStarted()) { 321 throw new IllegalArgumentException("CamelContext is not started"); 322 } 323 return context.getRouteController().stopRoute(getRouteId(), timeout, TimeUnit.SECONDS, abortAfterTimeout); 324 } 325 326 public void shutdown() throws Exception { 327 if (!context.getStatus().isStarted()) { 328 throw new IllegalArgumentException("CamelContext is not started"); 329 } 330 String routeId = getRouteId(); 331 context.getRouteController().stopRoute(routeId); 332 context.removeRoute(routeId); 333 } 334 335 public void shutdown(long timeout) throws Exception { 336 if (!context.getStatus().isStarted()) { 337 throw new IllegalArgumentException("CamelContext is not started"); 338 } 339 String routeId = getRouteId(); 340 context.getRouteController().stopRoute(routeId, timeout, TimeUnit.SECONDS); 341 context.removeRoute(routeId); 342 } 343 344 @Override 345 public boolean remove() throws Exception { 346 if (!context.getStatus().isStarted()) { 347 throw new IllegalArgumentException("CamelContext is not started"); 348 } 349 return context.removeRoute(getRouteId()); 350 } 351 352 @Override 353 public void restart() throws Exception { 354 restart(1); 355 } 356 357 @Override 358 public void restart(long delay) throws Exception { 359 stop(); 360 if (delay > 0) { 361 try { 362 LOG.debug("Sleeping {} seconds before starting route: {}", delay, getRouteId()); 363 Thread.sleep(delay * 1000); 364 } catch (InterruptedException e) { 365 // ignore 366 } 367 } 368 start(); 369 } 370 371 @Override 372 public String dumpRouteAsXml() throws Exception { 373 return dumpRouteAsXml(false, false); 374 } 375 376 @Override 377 public String dumpRouteAsXml(boolean resolvePlaceholders) throws Exception { 378 return dumpRouteAsXml(resolvePlaceholders, false); 379 } 380 381 @Override 382 public String dumpRouteAsXml(boolean resolvePlaceholders, boolean resolveDelegateEndpoints) throws Exception { 383 String id = route.getId(); 384 RouteDefinition def = context.getExtension(Model.class).getRouteDefinition(id); 385 if (def != null) { 386 ExtendedCamelContext ecc = context.adapt(ExtendedCamelContext.class); 387 return ecc.getModelToXMLDumper().dumpModelAsXml(context, def, resolvePlaceholders, resolveDelegateEndpoints); 388 } 389 390 return null; 391 } 392 393 @Override 394 public String dumpRouteStatsAsXml(boolean fullStats, boolean includeProcessors) throws Exception { 395 // in this logic we need to calculate the accumulated processing time for the processor in the route 396 // and hence why the logic is a bit more complicated to do this, as we need to calculate that from 397 // the bottom -> top of the route but this information is valuable for profiling routes 398 StringBuilder sb = new StringBuilder(); 399 400 // need to calculate this value first, as we need that value for the route stat 401 long processorAccumulatedTime = 0L; 402 403 // gather all the processors for this route, which requires JMX 404 if (includeProcessors) { 405 sb.append(" <processorStats>\n"); 406 MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer(); 407 if (server != null) { 408 // get all the processor mbeans and sort them accordingly to their index 409 String prefix = getContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : ""; 410 ObjectName query = ObjectName.getInstance( 411 jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=processors,*"); 412 Set<ObjectName> names = server.queryNames(query, null); 413 List<ManagedProcessorMBean> mps = new ArrayList<>(); 414 for (ObjectName on : names) { 415 ManagedProcessorMBean processor = context.getManagementStrategy().getManagementAgent().newProxyClient(on, 416 ManagedProcessorMBean.class); 417 418 // the processor must belong to this route 419 if (getRouteId().equals(processor.getRouteId())) { 420 mps.add(processor); 421 } 422 } 423 mps.sort(new OrderProcessorMBeans()); 424 425 // walk the processors in reverse order, and calculate the accumulated total time 426 Map<String, Long> accumulatedTimes = new HashMap<>(); 427 Collections.reverse(mps); 428 for (ManagedProcessorMBean processor : mps) { 429 processorAccumulatedTime += processor.getTotalProcessingTime(); 430 accumulatedTimes.put(processor.getProcessorId(), processorAccumulatedTime); 431 } 432 // and reverse back again 433 Collections.reverse(mps); 434 435 // and now add the sorted list of processors to the xml output 436 for (ManagedProcessorMBean processor : mps) { 437 int line = processor.getSourceLineNumber() != null ? processor.getSourceLineNumber() : -1; 438 sb.append(" <processorStat") 439 .append(String.format(" id=\"%s\" index=\"%s\" state=\"%s\" sourceLineNumber=\"%s\"", 440 processor.getProcessorId(), processor.getIndex(), processor.getState(), line)); 441 // do we have an accumulated time then append that 442 Long accTime = accumulatedTimes.get(processor.getProcessorId()); 443 if (accTime != null) { 444 sb.append(" accumulatedProcessingTime=\"").append(accTime).append("\""); 445 } 446 // use substring as we only want the attributes 447 sb.append(" ").append(processor.dumpStatsAsXml(fullStats).substring(7)).append("\n"); 448 } 449 } 450 sb.append(" </processorStats>\n"); 451 } 452 453 // route self time is route total - processor accumulated total) 454 long routeSelfTime = getTotalProcessingTime() - processorAccumulatedTime; 455 if (routeSelfTime < 0) { 456 // ensure we don't calculate that as negative 457 routeSelfTime = 0; 458 } 459 460 StringBuilder answer = new StringBuilder(); 461 answer.append("<routeStat").append(String.format(" id=\"%s\"", route.getId())) 462 .append(String.format(" state=\"%s\"", getState())); 463 if (sourceLocation != null) { 464 answer.append(String.format(" sourceLocation=\"%s\"", getSourceLocation())); 465 } 466 // use substring as we only want the attributes 467 String stat = dumpStatsAsXml(fullStats); 468 answer.append(" exchangesInflight=\"").append(getInflightExchanges()).append("\""); 469 answer.append(" selfProcessingTime=\"").append(routeSelfTime).append("\""); 470 InflightRepository.InflightExchange oldest = getOldestInflightEntry(); 471 if (oldest == null) { 472 answer.append(" oldestInflightExchangeId=\"\""); 473 answer.append(" oldestInflightDuration=\"\""); 474 } else { 475 answer.append(" oldestInflightExchangeId=\"").append(oldest.getExchange().getExchangeId()).append("\""); 476 answer.append(" oldestInflightDuration=\"").append(oldest.getDuration()).append("\""); 477 } 478 answer.append(" ").append(stat, 7, stat.length() - 2).append(">\n"); 479 480 if (includeProcessors) { 481 answer.append(sb); 482 } 483 484 answer.append("</routeStat>"); 485 return answer.toString(); 486 } 487 488 @Override 489 public String dumpStepStatsAsXml(boolean fullStats) throws Exception { 490 // in this logic we need to calculate the accumulated processing time for the processor in the route 491 // and hence why the logic is a bit more complicated to do this, as we need to calculate that from 492 // the bottom -> top of the route but this information is valuable for profiling routes 493 StringBuilder sb = new StringBuilder(); 494 495 // gather all the steps for this route, which requires JMX 496 sb.append(" <stepStats>\n"); 497 MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer(); 498 if (server != null) { 499 // get all the processor mbeans and sort them accordingly to their index 500 String prefix = getContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : ""; 501 ObjectName query = ObjectName 502 .getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=steps,*"); 503 Set<ObjectName> names = server.queryNames(query, null); 504 List<ManagedStepMBean> mps = new ArrayList<>(); 505 for (ObjectName on : names) { 506 ManagedStepMBean step 507 = context.getManagementStrategy().getManagementAgent().newProxyClient(on, ManagedStepMBean.class); 508 509 // the step must belong to this route 510 if (getRouteId().equals(step.getRouteId())) { 511 mps.add(step); 512 } 513 } 514 mps.sort(new OrderProcessorMBeans()); 515 516 // and now add the sorted list of steps to the xml output 517 for (ManagedStepMBean step : mps) { 518 int line = step.getSourceLineNumber() != null ? step.getSourceLineNumber() : -1; 519 sb.append(" <stepStat") 520 .append(String.format(" id=\"%s\" index=\"%s\" state=\"%s\" sourceLineNumber=\"%s\"", 521 step.getProcessorId(), 522 step.getIndex(), step.getState(), line)); 523 // use substring as we only want the attributes 524 sb.append(" ").append(step.dumpStatsAsXml(fullStats).substring(7)).append("\n"); 525 } 526 } 527 sb.append(" </stepStats>\n"); 528 529 StringBuilder answer = new StringBuilder(); 530 answer.append("<routeStat").append(String.format(" id=\"%s\"", route.getId())) 531 .append(String.format(" state=\"%s\"", getState())); 532 if (sourceLocation != null) { 533 answer.append(String.format(" sourceLocation=\"%s\"", getSourceLocation())); 534 } 535 // use substring as we only want the attributes 536 String stat = dumpStatsAsXml(fullStats); 537 answer.append(" exchangesInflight=\"").append(getInflightExchanges()).append("\""); 538 InflightRepository.InflightExchange oldest = getOldestInflightEntry(); 539 if (oldest == null) { 540 answer.append(" oldestInflightExchangeId=\"\""); 541 answer.append(" oldestInflightDuration=\"\""); 542 } else { 543 answer.append(" oldestInflightExchangeId=\"").append(oldest.getExchange().getExchangeId()).append("\""); 544 answer.append(" oldestInflightDuration=\"").append(oldest.getDuration()).append("\""); 545 } 546 answer.append(" ").append(stat, 7, stat.length() - 2).append(">\n"); 547 548 answer.append(sb); 549 550 answer.append("</routeStat>"); 551 return answer.toString(); 552 } 553 554 @Override 555 public String dumpRouteSourceLocationsAsXml() throws Exception { 556 StringBuilder sb = new StringBuilder(); 557 sb.append("<routeLocations>"); 558 559 MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer(); 560 if (server != null) { 561 String prefix = getContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : ""; 562 List<ManagedProcessorMBean> processors = new ArrayList<>(); 563 // gather all the processors for this CamelContext, which requires JMX 564 ObjectName query = ObjectName 565 .getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=processors,*"); 566 Set<ObjectName> names = server.queryNames(query, null); 567 for (ObjectName on : names) { 568 ManagedProcessorMBean processor 569 = context.getManagementStrategy().getManagementAgent().newProxyClient(on, ManagedProcessorMBean.class); 570 // the processor must belong to this route 571 if (getRouteId().equals(processor.getRouteId())) { 572 processors.add(processor); 573 } 574 } 575 processors.sort(new OrderProcessorMBeans()); 576 577 // grab route consumer 578 RouteDefinition rd = context.adapt(ModelCamelContext.class).getRouteDefinition(route.getRouteId()); 579 if (rd != null) { 580 String id = rd.getRouteId(); 581 int line = rd.getInput().getLineNumber(); 582 String location = getSourceLocation() != null ? getSourceLocation() : ""; 583 sb.append("\n <routeLocation") 584 .append(String.format( 585 " routeId=\"%s\" id=\"%s\" index=\"%s\" sourceLocation=\"%s\" sourceLineNumber=\"%s\"/>", 586 route.getRouteId(), id, 0, location, line)); 587 } 588 for (ManagedProcessorMBean processor : processors) { 589 // the step must belong to this route 590 if (route.getRouteId().equals(processor.getRouteId())) { 591 int line = processor.getSourceLineNumber() != null ? processor.getSourceLineNumber() : -1; 592 String location = processor.getSourceLocation() != null ? processor.getSourceLocation() : ""; 593 sb.append("\n <routeLocation") 594 .append(String.format( 595 " routeId=\"%s\" id=\"%s\" index=\"%s\" sourceLocation=\"%s\" sourceLineNumber=\"%s\"/>", 596 route.getRouteId(), processor.getProcessorId(), processor.getIndex(), location, line)); 597 } 598 } 599 } 600 sb.append("\n</routeLocations>"); 601 return sb.toString(); 602 } 603 604 @Override 605 public void reset(boolean includeProcessors) throws Exception { 606 reset(); 607 608 // and now reset all processors for this route 609 if (includeProcessors) { 610 MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer(); 611 if (server != null) { 612 // get all the processor mbeans and sort them accordingly to their index 613 String prefix = getContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : ""; 614 ObjectName query = ObjectName.getInstance( 615 jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=processors,*"); 616 QueryExp queryExp = Query.match(new AttributeValueExp("RouteId"), new StringValueExp(getRouteId())); 617 Set<ObjectName> names = server.queryNames(query, queryExp); 618 for (ObjectName name : names) { 619 server.invoke(name, "reset", null, null); 620 } 621 } 622 } 623 } 624 625 @Override 626 public boolean equals(Object o) { 627 return this == o || o != null && getClass() == o.getClass() && route.equals(((ManagedRoute) o).route); 628 } 629 630 @Override 631 public int hashCode() { 632 return route.hashCode(); 633 } 634 635 private InflightRepository.InflightExchange getOldestInflightEntry() { 636 return getContext().getInflightRepository().oldest(getRouteId()); 637 } 638 639 @Override 640 public Long getOldestInflightDuration() { 641 InflightRepository.InflightExchange oldest = getOldestInflightEntry(); 642 if (oldest == null) { 643 return null; 644 } else { 645 return oldest.getDuration(); 646 } 647 } 648 649 @Override 650 public String getOldestInflightExchangeId() { 651 InflightRepository.InflightExchange oldest = getOldestInflightEntry(); 652 if (oldest == null) { 653 return null; 654 } else { 655 return oldest.getExchange().getExchangeId(); 656 } 657 } 658 659 @Override 660 public Boolean getHasRouteController() { 661 return route.getRouteController() != null; 662 } 663 664 @Override 665 public RouteError getLastError() { 666 org.apache.camel.spi.RouteError error = route.getLastError(); 667 if (error == null) { 668 return null; 669 } else { 670 return new RouteError() { 671 @Override 672 public Phase getPhase() { 673 if (error.getPhase() != null) { 674 switch (error.getPhase()) { 675 case START: 676 return Phase.START; 677 case STOP: 678 return Phase.STOP; 679 case SUSPEND: 680 return Phase.SUSPEND; 681 case RESUME: 682 return Phase.RESUME; 683 case SHUTDOWN: 684 return Phase.SHUTDOWN; 685 case REMOVE: 686 return Phase.REMOVE; 687 default: 688 throw new IllegalStateException(); 689 } 690 } 691 return null; 692 } 693 694 @Override 695 public Throwable getException() { 696 return error.getException(); 697 } 698 }; 699 } 700 } 701 702 @Override 703 public Collection<String> processorIds() throws Exception { 704 List<String> ids = new ArrayList<>(); 705 706 MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer(); 707 if (server != null) { 708 String prefix = getContext().getManagementStrategy().getManagementAgent().getIncludeHostName() ? "*/" : ""; 709 // gather all the processors for this CamelContext, which requires JMX 710 ObjectName query = ObjectName 711 .getInstance(jmxDomain + ":context=" + prefix + getContext().getManagementName() + ",type=processors,*"); 712 Set<ObjectName> names = server.queryNames(query, null); 713 for (ObjectName on : names) { 714 ManagedProcessorMBean processor 715 = context.getManagementStrategy().getManagementAgent().newProxyClient(on, ManagedProcessorMBean.class); 716 // the processor must belong to this route 717 if (getRouteId().equals(processor.getRouteId())) { 718 ids.add(processor.getProcessorId()); 719 } 720 } 721 } 722 723 return ids; 724 } 725 726 private Integer getInflightExchanges() { 727 return (int) super.getExchangesInflight(); 728 } 729 730 /** 731 * Used for sorting the processor mbeans accordingly to their index. 732 */ 733 private static final class OrderProcessorMBeans implements Comparator<ManagedProcessorMBean>, Serializable { 734 735 @Override 736 public int compare(ManagedProcessorMBean o1, ManagedProcessorMBean o2) { 737 return o1.getIndex().compareTo(o2.getIndex()); 738 } 739 } 740}