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 */ 017 package org.apache.camel.management; 018 019 import java.net.UnknownHostException; 020 import java.util.concurrent.ThreadPoolExecutor; 021 import javax.management.MalformedObjectNameException; 022 import javax.management.ObjectName; 023 024 import org.apache.camel.CamelContext; 025 import org.apache.camel.Component; 026 import org.apache.camel.Consumer; 027 import org.apache.camel.Endpoint; 028 import org.apache.camel.ErrorHandlerFactory; 029 import org.apache.camel.Processor; 030 import org.apache.camel.Producer; 031 import org.apache.camel.Route; 032 import org.apache.camel.Service; 033 import org.apache.camel.builder.ErrorHandlerBuilderRef; 034 import org.apache.camel.model.ProcessorDefinition; 035 import org.apache.camel.spi.EventNotifier; 036 import org.apache.camel.spi.InterceptStrategy; 037 import org.apache.camel.spi.ManagementNamingStrategy; 038 import org.apache.camel.spi.RouteContext; 039 import org.apache.camel.util.InetAddressUtil; 040 import org.apache.camel.util.ObjectHelper; 041 042 /** 043 * Naming strategy used when registering MBeans. 044 */ 045 public class DefaultManagementNamingStrategy implements ManagementNamingStrategy { 046 public static final String VALUE_UNKNOWN = "unknown"; 047 public static final String KEY_NAME = "name"; 048 public static final String KEY_TYPE = "type"; 049 public static final String KEY_CONTEXT = "context"; 050 public static final String TYPE_CONTEXT = "context"; 051 public static final String TYPE_ENDPOINT = "endpoints"; 052 public static final String TYPE_PROCESSOR = "processors"; 053 public static final String TYPE_CONSUMER = "consumers"; 054 public static final String TYPE_PRODUCER = "producers"; 055 public static final String TYPE_ROUTE = "routes"; 056 public static final String TYPE_COMPONENT = "components"; 057 public static final String TYPE_TRACER = "tracer"; 058 public static final String TYPE_EVENT_NOTIFIER = "eventnotifiers"; 059 public static final String TYPE_ERRORHANDLER = "errorhandlers"; 060 public static final String TYPE_THREAD_POOL = "threadpools"; 061 public static final String TYPE_SERVICE = "services"; 062 public static final String TYPE_FABRIC = "fabric"; 063 064 protected String domainName; 065 protected String hostName = "localhost"; 066 067 public DefaultManagementNamingStrategy() { 068 this("org.apache.camel"); 069 } 070 071 public DefaultManagementNamingStrategy(String domainName) { 072 if (domainName != null) { 073 this.domainName = domainName; 074 } 075 try { 076 hostName = InetAddressUtil.getLocalHostName(); 077 } catch (UnknownHostException ex) { 078 // ignore, use the default "localhost" 079 } 080 } 081 082 public ObjectName getObjectNameForCamelContext(String managementName, String name) throws MalformedObjectNameException { 083 StringBuilder buffer = new StringBuilder(); 084 buffer.append(domainName).append(":"); 085 buffer.append(KEY_CONTEXT + "=").append(getContextId(managementName)).append(","); 086 buffer.append(KEY_TYPE + "=" + TYPE_CONTEXT + ","); 087 buffer.append(KEY_NAME + "=").append(ObjectName.quote(name)); 088 return createObjectName(buffer); 089 } 090 091 public ObjectName getObjectNameForCamelContext(CamelContext context) throws MalformedObjectNameException { 092 // prefer to use the given management name if previously assigned 093 String managementName = context.getManagementName(); 094 if (managementName == null) { 095 managementName = context.getManagementNameStrategy().getName(); 096 } 097 String name = context.getName(); 098 return getObjectNameForCamelContext(managementName, name); 099 } 100 101 public ObjectName getObjectNameForEndpoint(Endpoint endpoint) throws MalformedObjectNameException { 102 StringBuilder buffer = new StringBuilder(); 103 buffer.append(domainName).append(":"); 104 buffer.append(KEY_CONTEXT + "=").append(getContextId(endpoint.getCamelContext())).append(","); 105 buffer.append(KEY_TYPE + "=" + TYPE_ENDPOINT + ","); 106 buffer.append(KEY_NAME + "=").append(ObjectName.quote(getEndpointId(endpoint))); 107 return createObjectName(buffer); 108 } 109 110 public ObjectName getObjectNameForComponent(Component component, String name) throws MalformedObjectNameException { 111 StringBuilder buffer = new StringBuilder(); 112 buffer.append(domainName).append(":"); 113 buffer.append(KEY_CONTEXT + "=").append(getContextId(component.getCamelContext())).append(","); 114 buffer.append(KEY_TYPE + "=" + TYPE_COMPONENT + ","); 115 buffer.append(KEY_NAME + "=").append(ObjectName.quote(name)); 116 return createObjectName(buffer); 117 } 118 119 public ObjectName getObjectNameForProcessor(CamelContext context, Processor processor, ProcessorDefinition<?> definition) throws MalformedObjectNameException { 120 StringBuilder buffer = new StringBuilder(); 121 buffer.append(domainName).append(":"); 122 buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); 123 buffer.append(KEY_TYPE + "=").append(TYPE_PROCESSOR).append(","); 124 buffer.append(KEY_NAME + "=").append(ObjectName.quote(definition.getId())); 125 return createObjectName(buffer); 126 } 127 128 public ObjectName getObjectNameForErrorHandler(RouteContext routeContext, Processor errorHandler, ErrorHandlerFactory builder) throws MalformedObjectNameException { 129 StringBuilder buffer = new StringBuilder(); 130 buffer.append(domainName + ":" + KEY_CONTEXT + "=" + getContextId(routeContext.getCamelContext()) + "," 131 + KEY_TYPE + "=" + TYPE_ERRORHANDLER + ","); 132 133 // we want to only register one instance of the various error handler types and thus do some lookup 134 // if its a ErrorHandlerBuildRef. We need a bit of work to do that as there are potential indirection. 135 String ref = null; 136 if (builder instanceof ErrorHandlerBuilderRef) { 137 ErrorHandlerBuilderRef builderRef = (ErrorHandlerBuilderRef) builder; 138 139 // it has not then its an indirection and we should do some work to lookup the real builder 140 ref = builderRef.getRef(); 141 builder = ErrorHandlerBuilderRef.lookupErrorHandlerBuilder(routeContext, builderRef.getRef()); 142 143 // must do a 2nd lookup in case this is also a reference 144 // (this happens with spring DSL using errorHandlerRef on <route> as it gets a bit 145 // complex with indirections for error handler references 146 if (builder instanceof ErrorHandlerBuilderRef) { 147 builderRef = (ErrorHandlerBuilderRef) builder; 148 // does it refer to a non default error handler then do a 2nd lookup 149 if (!builderRef.getRef().equals(ErrorHandlerBuilderRef.DEFAULT_ERROR_HANDLER_BUILDER)) { 150 builder = ErrorHandlerBuilderRef.lookupErrorHandlerBuilder(routeContext, builderRef.getRef()); 151 ref = builderRef.getRef(); 152 } 153 } 154 } 155 156 if (ref != null) { 157 String name = builder.getClass().getSimpleName() + "(ref:" + ref + ")"; 158 buffer.append(KEY_NAME + "=").append(ObjectName.quote(name)); 159 } else { 160 // create a name based on its instance 161 buffer.append(KEY_NAME + "=") 162 .append(builder.getClass().getSimpleName()) 163 .append("(").append(ObjectHelper.getIdentityHashCode(builder)).append(")"); 164 } 165 166 return createObjectName(buffer); 167 } 168 169 public ObjectName getObjectNameForConsumer(CamelContext context, Consumer consumer) throws MalformedObjectNameException { 170 StringBuilder buffer = new StringBuilder(); 171 buffer.append(domainName).append(":"); 172 buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); 173 buffer.append(KEY_TYPE + "=").append(TYPE_CONSUMER).append(","); 174 175 String name = consumer.getClass().getSimpleName(); 176 if (ObjectHelper.isEmpty(name)) { 177 name = "Consumer"; 178 } 179 buffer.append(KEY_NAME + "=") 180 .append(name) 181 .append("(").append(ObjectHelper.getIdentityHashCode(consumer)).append(")"); 182 return createObjectName(buffer); 183 } 184 185 public ObjectName getObjectNameForProducer(CamelContext context, Producer producer) throws MalformedObjectNameException { 186 StringBuilder buffer = new StringBuilder(); 187 buffer.append(domainName).append(":"); 188 buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); 189 buffer.append(KEY_TYPE + "=").append(TYPE_PRODUCER).append(","); 190 191 String name = producer.getClass().getSimpleName(); 192 if (ObjectHelper.isEmpty(name)) { 193 name = "Producer"; 194 } 195 buffer.append(KEY_NAME + "=") 196 .append(name) 197 .append("(").append(ObjectHelper.getIdentityHashCode(producer)).append(")"); 198 return createObjectName(buffer); 199 } 200 201 public ObjectName getObjectNameForTracer(CamelContext context, InterceptStrategy tracer) throws MalformedObjectNameException { 202 StringBuilder buffer = new StringBuilder(); 203 buffer.append(domainName).append(":"); 204 buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); 205 buffer.append(KEY_TYPE + "=" + TYPE_TRACER + ","); 206 buffer.append(KEY_NAME + "=") 207 .append("Tracer") 208 .append("(").append(ObjectHelper.getIdentityHashCode(tracer)).append(")"); 209 return createObjectName(buffer); 210 } 211 212 public ObjectName getObjectNameForEventNotifier(CamelContext context, EventNotifier eventNotifier) throws MalformedObjectNameException { 213 StringBuilder buffer = new StringBuilder(); 214 buffer.append(domainName).append(":"); 215 buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); 216 buffer.append(KEY_TYPE + "=" + TYPE_EVENT_NOTIFIER + ","); 217 218 if (eventNotifier instanceof JmxNotificationEventNotifier) { 219 // JMX notifier shall have an easy to use name 220 buffer.append(KEY_NAME + "=").append("JmxEventNotifier"); 221 } else { 222 // others can be per instance 223 buffer.append(KEY_NAME + "=") 224 .append("EventNotifier") 225 .append("(").append(ObjectHelper.getIdentityHashCode(eventNotifier)).append(")"); 226 } 227 return createObjectName(buffer); 228 } 229 230 public ObjectName getObjectNameForRoute(Route route) throws MalformedObjectNameException { 231 Endpoint ep = route.getEndpoint(); 232 String id = route.getId(); 233 234 StringBuilder buffer = new StringBuilder(); 235 buffer.append(domainName).append(":"); 236 buffer.append(KEY_CONTEXT + "=").append(getContextId(ep.getCamelContext())).append(","); 237 buffer.append(KEY_TYPE + "=" + TYPE_ROUTE + ","); 238 buffer.append(KEY_NAME + "=").append(ObjectName.quote(id)); 239 return createObjectName(buffer); 240 } 241 242 public ObjectName getObjectNameForService(CamelContext context, Service service) throws MalformedObjectNameException { 243 StringBuilder buffer = new StringBuilder(); 244 buffer.append(domainName).append(":"); 245 buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); 246 // special for fabric 247 if (service.getClass().getCanonicalName().startsWith("org.apache.camel.fabric")) { 248 buffer.append(KEY_TYPE + "=" + TYPE_FABRIC + ","); 249 } else { 250 buffer.append(KEY_TYPE + "=" + TYPE_SERVICE + ","); 251 } 252 buffer.append(KEY_NAME + "=") 253 .append(service.getClass().getSimpleName()) 254 .append("(").append(ObjectHelper.getIdentityHashCode(service)).append(")"); 255 return createObjectName(buffer); 256 } 257 258 public ObjectName getObjectNameForThreadPool(CamelContext context, ThreadPoolExecutor threadPool, String id, String sourceId) 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_THREAD_POOL + ","); 263 264 String name = id; 265 if (sourceId != null) { 266 // provide source id if we know it, this helps end user to know where the pool is used 267 name = name + "(" + sourceId + ")"; 268 } 269 buffer.append(KEY_NAME + "=").append(ObjectName.quote(name)); 270 return createObjectName(buffer); 271 } 272 273 public String getDomainName() { 274 return domainName; 275 } 276 277 public void setDomainName(String domainName) { 278 this.domainName = domainName; 279 } 280 281 public String getHostName() { 282 return hostName; 283 } 284 285 public void setHostName(String hostName) { 286 this.hostName = hostName; 287 } 288 289 protected String getContextId(CamelContext context) { 290 if (context == null) { 291 return getContextId(VALUE_UNKNOWN); 292 } else { 293 String name = context.getManagementName() != null ? context.getManagementName() : context.getName(); 294 return getContextId(name); 295 } 296 } 297 298 protected String getContextId(String name) { 299 return hostName + "/" + (name != null ? name : VALUE_UNKNOWN); 300 } 301 302 protected String getEndpointId(Endpoint ep) { 303 if (ep.isSingleton()) { 304 return ep.getEndpointKey(); 305 } else { 306 // non singleton then add hashcoded id 307 String uri = ep.getEndpointKey(); 308 int pos = uri.indexOf('?'); 309 String id = (pos == -1) ? uri : uri.substring(0, pos); 310 id += "?id=" + ObjectHelper.getIdentityHashCode(ep); 311 return id; 312 } 313 } 314 315 /** 316 * Factory method to create an ObjectName escaping any required characters 317 */ 318 protected ObjectName createObjectName(StringBuilder buffer) throws MalformedObjectNameException { 319 String text = buffer.toString(); 320 try { 321 return new ObjectName(text); 322 } catch (MalformedObjectNameException e) { 323 throw new MalformedObjectNameException("Could not create ObjectName from: " + text + ". Reason: " + e); 324 } 325 } 326 }