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