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