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; 018 019import java.net.UnknownHostException; 020import java.util.concurrent.ThreadPoolExecutor; 021 022import javax.management.MalformedObjectNameException; 023import javax.management.ObjectName; 024 025import org.apache.camel.CamelContext; 026import org.apache.camel.CamelContextAware; 027import org.apache.camel.Component; 028import org.apache.camel.Consumer; 029import org.apache.camel.Endpoint; 030import org.apache.camel.NamedNode; 031import org.apache.camel.Processor; 032import org.apache.camel.Producer; 033import org.apache.camel.Service; 034import org.apache.camel.StaticService; 035import org.apache.camel.cluster.CamelClusterService; 036import org.apache.camel.management.mbean.ManagedBacklogDebugger; 037import org.apache.camel.management.mbean.ManagedBacklogTracer; 038import org.apache.camel.management.mbean.ManagedCamelContext; 039import org.apache.camel.management.mbean.ManagedCamelHealth; 040import org.apache.camel.management.mbean.ManagedClusterService; 041import org.apache.camel.management.mbean.ManagedComponent; 042import org.apache.camel.management.mbean.ManagedConsumer; 043import org.apache.camel.management.mbean.ManagedDataFormat; 044import org.apache.camel.management.mbean.ManagedDumpRouteStrategy; 045import org.apache.camel.management.mbean.ManagedEndpoint; 046import org.apache.camel.management.mbean.ManagedEventNotifier; 047import org.apache.camel.management.mbean.ManagedProcessor; 048import org.apache.camel.management.mbean.ManagedProducer; 049import org.apache.camel.management.mbean.ManagedRoute; 050import org.apache.camel.management.mbean.ManagedRouteController; 051import org.apache.camel.management.mbean.ManagedService; 052import org.apache.camel.management.mbean.ManagedStep; 053import org.apache.camel.management.mbean.ManagedSupervisingRouteController; 054import org.apache.camel.management.mbean.ManagedThreadPool; 055import org.apache.camel.management.mbean.ManagedTracer; 056import org.apache.camel.spi.DataFormat; 057import org.apache.camel.spi.EventNotifier; 058import org.apache.camel.spi.ManagementObjectNameStrategy; 059import org.apache.camel.spi.RouteController; 060import org.apache.camel.util.InetAddressUtil; 061import org.apache.camel.util.ObjectHelper; 062import org.apache.camel.util.StringHelper; 063import org.apache.camel.util.URISupport; 064 065/** 066 * Naming strategy used when registering MBeans. 067 */ 068public class DefaultManagementObjectNameStrategy implements ManagementObjectNameStrategy, CamelContextAware { 069 public static final String VALUE_UNKNOWN = "unknown"; 070 public static final String KEY_NAME = "name"; 071 public static final String KEY_TYPE = "type"; 072 public static final String KEY_CONTEXT = "context"; 073 public static final String TYPE_CONTEXT = "context"; 074 public static final String TYPE_HEALTH = "health"; 075 public static final String TYPE_ENDPOINT = "endpoints"; 076 public static final String TYPE_DATAFORMAT = "dataformats"; 077 public static final String TYPE_PROCESSOR = "processors"; 078 public static final String TYPE_CONSUMER = "consumers"; 079 public static final String TYPE_PRODUCER = "producers"; 080 public static final String TYPE_ROUTE = "routes"; 081 public static final String TYPE_COMPONENT = "components"; 082 public static final String TYPE_STEP = "steps"; 083 public static final String TYPE_TRACER = "tracer"; 084 public static final String TYPE_EVENT_NOTIFIER = "eventnotifiers"; 085 public static final String TYPE_THREAD_POOL = "threadpools"; 086 public static final String TYPE_SERVICE = "services"; 087 public static final String TYPE_HA = "clusterservices"; 088 089 protected String domainName; 090 protected String hostName = "localhost"; 091 protected CamelContext camelContext; 092 093 public DefaultManagementObjectNameStrategy() { 094 this(null); 095 // default constructor needed for <bean> style configuration 096 } 097 098 public DefaultManagementObjectNameStrategy(String domainName) { 099 this.domainName = domainName != null ? domainName : "org.apache.camel"; 100 try { 101 hostName = InetAddressUtil.getLocalHostName(); 102 } catch (UnknownHostException ex) { 103 // ignore, use the default "localhost" 104 } 105 } 106 107 @Override 108 public CamelContext getCamelContext() { 109 return camelContext; 110 } 111 112 @Override 113 public void setCamelContext(CamelContext camelContext) { 114 this.camelContext = camelContext; 115 } 116 117 @Override 118 public ObjectName getObjectName(Object managedObject) throws MalformedObjectNameException { 119 if (managedObject == null) { 120 return null; 121 } 122 ObjectName objectName = null; 123 if (managedObject instanceof ManagedCamelContext) { 124 ManagedCamelContext mcc = (ManagedCamelContext) managedObject; 125 objectName = getObjectNameForCamelContext(mcc.getContext()); 126 } else if (managedObject instanceof ManagedCamelHealth) { 127 ManagedCamelHealth mch = (ManagedCamelHealth) managedObject; 128 objectName = getObjectNameForCamelHealth(mch.getContext()); 129 } else if (managedObject instanceof ManagedRouteController) { 130 ManagedRouteController mrc = (ManagedRouteController) managedObject; 131 objectName = getObjectNameForRouteController(mrc.getContext(), mrc.getRouteController()); 132 } else if (managedObject instanceof ManagedSupervisingRouteController) { 133 ManagedSupervisingRouteController mrc = (ManagedSupervisingRouteController) managedObject; 134 objectName = getObjectNameForRouteController(mrc.getContext(), mrc.getRouteController()); 135 } else if (managedObject instanceof ManagedComponent) { 136 ManagedComponent mc = (ManagedComponent) managedObject; 137 objectName = getObjectNameForComponent(mc.getComponent(), mc.getComponentName()); 138 } else if (managedObject instanceof ManagedDataFormat) { 139 ManagedDataFormat md = (ManagedDataFormat) managedObject; 140 objectName = getObjectNameForDataFormat(md.getContext(), md.getDataFormat()); 141 } else if (managedObject instanceof ManagedEndpoint) { 142 ManagedEndpoint me = (ManagedEndpoint) managedObject; 143 objectName = getObjectNameForEndpoint(me.getEndpoint()); 144 } else if (managedObject instanceof Endpoint) { 145 objectName = getObjectNameForEndpoint((Endpoint) managedObject); 146 } else if (managedObject instanceof ManagedRoute) { 147 ManagedRoute mr = (ManagedRoute) managedObject; 148 objectName = getObjectNameForRoute(mr.getRoute()); 149 } else if (managedObject instanceof ManagedStep) { 150 ManagedStep mp = (ManagedStep) managedObject; 151 objectName = getObjectNameForStep(mp.getContext(), mp.getProcessor(), mp.getDefinition()); 152 } else if (managedObject instanceof ManagedProcessor) { 153 ManagedProcessor mp = (ManagedProcessor) managedObject; 154 objectName = getObjectNameForProcessor(mp.getContext(), mp.getProcessor(), mp.getDefinition()); 155 } else if (managedObject instanceof ManagedConsumer) { 156 ManagedConsumer ms = (ManagedConsumer) managedObject; 157 objectName = getObjectNameForConsumer(ms.getContext(), ms.getConsumer()); 158 } else if (managedObject instanceof ManagedProducer) { 159 ManagedProducer ms = (ManagedProducer) managedObject; 160 objectName = getObjectNameForProducer(ms.getContext(), ms.getProducer()); 161 } else if (managedObject instanceof ManagedBacklogTracer) { 162 ManagedBacklogTracer mt = (ManagedBacklogTracer) managedObject; 163 objectName = getObjectNameForTracer(mt.getContext(), mt.getBacklogTracer()); 164 } else if (managedObject instanceof ManagedBacklogDebugger) { 165 ManagedBacklogDebugger md = (ManagedBacklogDebugger) managedObject; 166 objectName = getObjectNameForTracer(md.getContext(), md.getBacklogDebugger()); 167 } else if (managedObject instanceof ManagedDumpRouteStrategy) { 168 ManagedDumpRouteStrategy md = (ManagedDumpRouteStrategy) managedObject; 169 objectName = getObjectNameForService(md.getContext(), md.getDumpRoutesStrategy()); 170 } else if (managedObject instanceof ManagedEventNotifier) { 171 ManagedEventNotifier men = (ManagedEventNotifier) managedObject; 172 objectName = getObjectNameForEventNotifier(men.getContext(), men.getEventNotifier()); 173 } else if (managedObject instanceof ManagedTracer) { 174 ManagedTracer mt = (ManagedTracer) managedObject; 175 objectName = getObjectNameForTracer(mt.getContext(), mt.getTracer()); 176 } else if (managedObject instanceof ManagedThreadPool) { 177 ManagedThreadPool mes = (ManagedThreadPool) managedObject; 178 objectName = getObjectNameForThreadPool(mes.getContext(), mes.getThreadPool(), mes.getId(), mes.getSourceId()); 179 } else if (managedObject instanceof ManagedClusterService) { 180 ManagedClusterService mcs = (ManagedClusterService) managedObject; 181 objectName = getObjectNameForClusterService(mcs.getContext(), mcs.getService()); 182 } else if (managedObject instanceof ManagedService) { 183 // check for managed service should be last 184 ManagedService ms = (ManagedService) managedObject; 185 // skip endpoints as they are already managed 186 if (ms.getService() instanceof Endpoint) { 187 return null; 188 } 189 objectName = getObjectNameForService(ms.getContext(), ms.getService()); 190 } 191 192 return objectName; 193 } 194 195 @Override 196 public ObjectName getObjectNameForCamelContext(String managementName, String name) throws MalformedObjectNameException { 197 StringBuilder buffer = new StringBuilder(); 198 buffer.append(domainName).append(":"); 199 buffer.append(KEY_CONTEXT + "=").append(getContextId(managementName)).append(","); 200 buffer.append(KEY_TYPE + "=" + TYPE_CONTEXT + ","); 201 buffer.append(KEY_NAME + "=").append(ObjectName.quote(name)); 202 return createObjectName(buffer); 203 } 204 205 @Override 206 public ObjectName getObjectNameForCamelContext(CamelContext context) throws MalformedObjectNameException { 207 // prefer to use the given management name if previously assigned 208 String managementName = context.getManagementName(); 209 if (managementName == null) { 210 managementName = context.getManagementNameStrategy().getName(); 211 } 212 String name = context.getName(); 213 return getObjectNameForCamelContext(managementName, name); 214 } 215 216 @Override 217 public ObjectName getObjectNameForCamelHealth(CamelContext context) throws MalformedObjectNameException { 218 // prefer to use the given management name if previously assigned 219 String managementName = context.getManagementName(); 220 if (managementName == null) { 221 managementName = context.getManagementNameStrategy().getName(); 222 } 223 224 StringBuilder buffer = new StringBuilder(); 225 buffer.append(domainName).append(":"); 226 buffer.append(KEY_CONTEXT + "=").append(getContextId(managementName)).append(","); 227 buffer.append(KEY_TYPE + "=" + TYPE_HEALTH + ","); 228 buffer.append(KEY_NAME + "=").append("DefaultHealthCheck"); 229 230 return createObjectName(buffer); 231 } 232 233 @Override 234 public ObjectName getObjectNameForRouteController(CamelContext context, RouteController routeController) 235 throws MalformedObjectNameException { 236 // prefer to use the given management name if previously assigned 237 String managementName = context.getManagementName(); 238 if (managementName == null) { 239 managementName = context.getManagementNameStrategy().getName(); 240 } 241 242 StringBuilder buffer = new StringBuilder(); 243 buffer.append(domainName).append(":"); 244 buffer.append(KEY_CONTEXT + "=").append(getContextId(managementName)).append(","); 245 buffer.append(KEY_TYPE + "=" + TYPE_SERVICE + ","); 246 buffer.append(KEY_NAME + "=").append(routeController.getClass().getSimpleName()); 247 248 return createObjectName(buffer); 249 } 250 251 @Override 252 public ObjectName getObjectNameForEndpoint(Endpoint endpoint) throws MalformedObjectNameException { 253 StringBuilder buffer = new StringBuilder(); 254 buffer.append(domainName).append(":"); 255 buffer.append(KEY_CONTEXT + "=").append(getContextId(endpoint.getCamelContext())).append(","); 256 buffer.append(KEY_TYPE + "=" + TYPE_ENDPOINT + ","); 257 buffer.append(KEY_NAME + "=").append(ObjectName.quote(getEndpointId(endpoint))); 258 return createObjectName(buffer); 259 } 260 261 @Override 262 public ObjectName getObjectNameForDataFormat(CamelContext context, DataFormat dataFormat) 263 throws MalformedObjectNameException { 264 StringBuilder buffer = new StringBuilder(); 265 buffer.append(domainName).append(":"); 266 buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); 267 buffer.append(KEY_TYPE + "=" + TYPE_DATAFORMAT + ","); 268 buffer.append(KEY_NAME + "=").append(dataFormat.getClass().getSimpleName()); 269 if (!(dataFormat instanceof StaticService)) { 270 buffer.append("(").append(ObjectHelper.getIdentityHashCode(dataFormat)).append(")"); 271 } 272 return createObjectName(buffer); 273 } 274 275 @Override 276 public ObjectName getObjectNameForComponent(Component component, String name) throws MalformedObjectNameException { 277 StringBuilder buffer = new StringBuilder(); 278 buffer.append(domainName).append(":"); 279 buffer.append(KEY_CONTEXT + "=").append(getContextId(component.getCamelContext())).append(","); 280 buffer.append(KEY_TYPE + "=" + TYPE_COMPONENT + ","); 281 buffer.append(KEY_NAME + "=").append(ObjectName.quote(name)); 282 return createObjectName(buffer); 283 } 284 285 @Override 286 public ObjectName getObjectNameForProcessor(CamelContext context, Processor processor, NamedNode definition) 287 throws MalformedObjectNameException { 288 StringBuilder buffer = new StringBuilder(); 289 buffer.append(domainName).append(":"); 290 buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); 291 buffer.append(KEY_TYPE + "=").append(TYPE_PROCESSOR).append(","); 292 String id = definition.getId(); 293 String prefix = definition.getNodePrefixId(); 294 if (prefix != null) { 295 id = prefix + id; 296 } 297 buffer.append(KEY_NAME + "=").append(ObjectName.quote(id)); 298 return createObjectName(buffer); 299 } 300 301 @Override 302 public ObjectName getObjectNameForStep(CamelContext context, Processor processor, NamedNode definition) 303 throws MalformedObjectNameException { 304 StringBuilder buffer = new StringBuilder(); 305 buffer.append(domainName).append(":"); 306 buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); 307 buffer.append(KEY_TYPE + "=").append(TYPE_STEP).append(","); 308 String id = definition.getId(); 309 String prefix = definition.getNodePrefixId(); 310 if (prefix != null) { 311 id = prefix + id; 312 } 313 buffer.append(KEY_NAME + "=").append(ObjectName.quote(id)); 314 return createObjectName(buffer); 315 } 316 317 @Override 318 public ObjectName getObjectNameForConsumer(CamelContext context, Consumer consumer) throws MalformedObjectNameException { 319 StringBuilder buffer = new StringBuilder(); 320 buffer.append(domainName).append(":"); 321 buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); 322 buffer.append(KEY_TYPE + "=").append(TYPE_CONSUMER).append(","); 323 324 String name = consumer.getClass().getSimpleName(); 325 if (ObjectHelper.isEmpty(name)) { 326 name = "Consumer"; 327 } 328 buffer.append(KEY_NAME + "=") 329 .append(name) 330 .append("(").append(ObjectHelper.getIdentityHashCode(consumer)).append(")"); 331 return createObjectName(buffer); 332 } 333 334 @Override 335 public ObjectName getObjectNameForProducer(CamelContext context, Producer producer) throws MalformedObjectNameException { 336 StringBuilder buffer = new StringBuilder(); 337 buffer.append(domainName).append(":"); 338 buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); 339 buffer.append(KEY_TYPE + "=").append(TYPE_PRODUCER).append(","); 340 341 String name = producer.getClass().getSimpleName(); 342 if (ObjectHelper.isEmpty(name)) { 343 name = "Producer"; 344 } 345 buffer.append(KEY_NAME + "=") 346 .append(name) 347 .append("(").append(ObjectHelper.getIdentityHashCode(producer)).append(")"); 348 return createObjectName(buffer); 349 } 350 351 @Override 352 public ObjectName getObjectNameForTracer(CamelContext context, Service tracer) throws MalformedObjectNameException { 353 // use the simple name of the class as the mbean name (eg Tracer, BacklogTracer, BacklogDebugger) 354 String name = tracer.getClass().getSimpleName(); 355 // backwards compatible names 356 if ("DefaultBacklogDebugger".equals(name)) { 357 name = "BacklogDebugger"; 358 } else if ("DefaultBacklogTracer".equals(name)) { 359 name = "BacklogTracer"; 360 } 361 362 StringBuilder buffer = new StringBuilder(); 363 buffer.append(domainName).append(":"); 364 buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); 365 buffer.append(KEY_TYPE + "=" + TYPE_TRACER + ","); 366 buffer.append(KEY_NAME + "=").append(name); 367 return createObjectName(buffer); 368 } 369 370 @Override 371 public ObjectName getObjectNameForEventNotifier(CamelContext context, EventNotifier eventNotifier) 372 throws MalformedObjectNameException { 373 StringBuilder buffer = new StringBuilder(); 374 buffer.append(domainName).append(":"); 375 buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); 376 buffer.append(KEY_TYPE + "=" + TYPE_EVENT_NOTIFIER + ","); 377 378 if (eventNotifier instanceof JmxNotificationEventNotifier) { 379 // JMX notifier shall have an easy to use name 380 buffer.append(KEY_NAME + "=").append("JmxEventNotifier"); 381 } else { 382 // others can be per instance 383 buffer.append(KEY_NAME + "=") 384 .append("EventNotifier") 385 .append("(").append(ObjectHelper.getIdentityHashCode(eventNotifier)).append(")"); 386 } 387 return createObjectName(buffer); 388 } 389 390 @Override 391 public ObjectName getObjectNameForRoute(org.apache.camel.Route route) throws MalformedObjectNameException { 392 StringBuilder buffer = new StringBuilder(); 393 buffer.append(domainName).append(":"); 394 buffer.append(KEY_CONTEXT + "=").append(getContextId(route.getCamelContext())).append(","); 395 buffer.append(KEY_TYPE + "=" + TYPE_ROUTE + ","); 396 buffer.append(KEY_NAME + "=").append(ObjectName.quote(route.getId())); 397 return createObjectName(buffer); 398 } 399 400 @Override 401 public ObjectName getObjectNameForService(CamelContext context, Service service) throws MalformedObjectNameException { 402 StringBuilder buffer = new StringBuilder(); 403 buffer.append(domainName).append(":"); 404 buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); 405 buffer.append(KEY_TYPE + "=" + TYPE_SERVICE + ","); 406 buffer.append(KEY_NAME + "=").append(service.getClass().getSimpleName()); 407 if (!(service instanceof StaticService)) { 408 buffer.append("(").append(ObjectHelper.getIdentityHashCode(service)).append(")"); 409 } 410 return createObjectName(buffer); 411 } 412 413 @Override 414 public ObjectName getObjectNameForClusterService(CamelContext context, CamelClusterService service) 415 throws MalformedObjectNameException { 416 StringBuilder buffer = new StringBuilder(); 417 buffer.append(domainName).append(":"); 418 buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); 419 buffer.append(KEY_TYPE + "=" + TYPE_HA + ","); 420 buffer.append(KEY_NAME + "=").append(service.getClass().getSimpleName()); 421 if (!(service instanceof StaticService)) { 422 buffer.append("(").append(ObjectHelper.getIdentityHashCode(service)).append(")"); 423 } 424 return createObjectName(buffer); 425 } 426 427 @Override 428 public ObjectName getObjectNameForThreadPool( 429 CamelContext context, ThreadPoolExecutor threadPool, String id, String sourceId) 430 throws MalformedObjectNameException { 431 StringBuilder buffer = new StringBuilder(); 432 buffer.append(domainName).append(":"); 433 buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); 434 buffer.append(KEY_TYPE + "=" + TYPE_THREAD_POOL + ","); 435 436 String name = id; 437 if (sourceId != null) { 438 // provide source id if we know it, this helps end user to know where the pool is used 439 name = name + "(" + sourceId + ")"; 440 } 441 buffer.append(KEY_NAME + "=").append(ObjectName.quote(name)); 442 return createObjectName(buffer); 443 } 444 445 public String getDomainName() { 446 return domainName; 447 } 448 449 public void setDomainName(String domainName) { 450 this.domainName = domainName; 451 } 452 453 public String getHostName() { 454 return hostName; 455 } 456 457 public void setHostName(String hostName) { 458 this.hostName = hostName; 459 } 460 461 protected String getContextId(CamelContext context) { 462 if (context == null) { 463 return getContextId(VALUE_UNKNOWN); 464 } else { 465 String name = context.getManagementName() != null ? context.getManagementName() : context.getName(); 466 return getContextId(name); 467 } 468 } 469 470 protected String getContextId(String name) { 471 boolean includeHostName 472 = camelContext != null && camelContext.getManagementStrategy().getManagementAgent().getIncludeHostName(); 473 if (includeHostName) { 474 return hostName + "/" + (name != null ? name : VALUE_UNKNOWN); 475 } else { 476 return name != null ? name : VALUE_UNKNOWN; 477 } 478 } 479 480 protected String getEndpointId(Endpoint ep) { 481 String answer = doGetEndpointId(ep); 482 boolean sanitize = camelContext != null && camelContext.getManagementStrategy().getManagementAgent().getMask(); 483 if (sanitize) { 484 // use xxxxxx as replacements as * has to be quoted for MBean names 485 answer = URISupport.sanitizeUri(answer); 486 } 487 return answer; 488 } 489 490 private String doGetEndpointId(Endpoint ep) { 491 if (ep.isSingleton()) { 492 return ep.getEndpointKey(); 493 } else { 494 // non singleton then add hashcoded id 495 String uri = ep.getEndpointKey(); 496 String id = StringHelper.before(uri, "?", uri); 497 id += "?id=" + ObjectHelper.getIdentityHashCode(ep); 498 return id; 499 } 500 } 501 502 /** 503 * Factory method to create an ObjectName escaping any required characters 504 */ 505 protected ObjectName createObjectName(StringBuilder buffer) throws MalformedObjectNameException { 506 String text = buffer.toString(); 507 try { 508 return new ObjectName(text); 509 } catch (MalformedObjectNameException e) { 510 throw new MalformedObjectNameException("Could not create ObjectName from: " + text + ". Reason: " + e); 511 } 512 } 513}