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