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.InetAddress;
020    import java.net.UnknownHostException;
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.Processor;
029    import org.apache.camel.Producer;
030    import org.apache.camel.Route;
031    import org.apache.camel.Service;
032    import org.apache.camel.builder.ErrorHandlerBuilder;
033    import org.apache.camel.builder.ErrorHandlerBuilderRef;
034    import org.apache.camel.model.ProcessorDefinition;
035    import org.apache.camel.spi.InterceptStrategy;
036    import org.apache.camel.spi.ManagementNamingStrategy;
037    import org.apache.camel.spi.RouteContext;
038    import org.apache.camel.util.ObjectHelper;
039    
040    /**
041     * Naming strategy used when registering MBeans.
042     */
043    public class DefaultManagementNamingStrategy implements ManagementNamingStrategy {
044        public static final String VALUE_UNKNOWN = "unknown";
045        public static final String KEY_NAME = "name";
046        public static final String KEY_TYPE = "type";
047        public static final String KEY_CONTEXT = "context";
048        public static final String TYPE_CONTEXT = "context";
049        public static final String TYPE_ENDPOINT = "endpoints";
050        public static final String TYPE_PROCESSOR = "processors";
051        public static final String TYPE_CONSUMER = "consumers";
052        public static final String TYPE_PRODUCER = "producers";
053        public static final String TYPE_ROUTE = "routes";
054        public static final String TYPE_COMPONENT = "components";
055        public static final String TYPE_TRACER = "tracer";
056        public static final String TYPE_ERRORHANDLER = "errorhandlers";
057        public static final String TYPE_SERVICE = "services";
058    
059        protected String domainName;
060        protected String hostName = "localhost";
061    
062        public DefaultManagementNamingStrategy() {
063            this("org.apache.camel");
064        }
065    
066        public DefaultManagementNamingStrategy(String domainName) {
067            if (domainName != null) {
068                this.domainName = domainName;
069            }
070            try {
071                hostName = InetAddress.getLocalHost().getHostName();
072            } catch (UnknownHostException ex) {
073                // ignore, use the default "localhost"
074            }
075        }
076    
077        public ObjectName getObjectNameForCamelContext(CamelContext context) throws MalformedObjectNameException {
078            StringBuffer buffer = new StringBuffer();
079            buffer.append(domainName).append(":");
080            buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(",");
081            buffer.append(KEY_TYPE + "=" + TYPE_CONTEXT + ",");
082            buffer.append(KEY_NAME + "=").append(ObjectName.quote(context.getName()));
083            return createObjectName(buffer);
084        }
085    
086        public ObjectName getObjectNameForEndpoint(Endpoint endpoint) throws MalformedObjectNameException {
087            StringBuffer buffer = new StringBuffer();
088            buffer.append(domainName).append(":");
089            buffer.append(KEY_CONTEXT + "=").append(getContextId(endpoint.getCamelContext())).append(",");
090            buffer.append(KEY_TYPE + "=" + TYPE_ENDPOINT + ",");
091            buffer.append(KEY_NAME + "=").append(ObjectName.quote(getEndpointId(endpoint)));
092            return createObjectName(buffer);
093        }
094    
095        public ObjectName getObjectNameForComponent(Component component, String name) throws MalformedObjectNameException {
096            StringBuffer buffer = new StringBuffer();
097            buffer.append(domainName).append(":");
098            buffer.append(KEY_CONTEXT + "=").append(getContextId(component.getCamelContext())).append(",");
099            buffer.append(KEY_TYPE + "=" + TYPE_COMPONENT + ",");
100            buffer.append(KEY_NAME + "=").append(ObjectName.quote(name));
101            return createObjectName(buffer);
102        }
103    
104        public ObjectName getObjectNameForProcessor(CamelContext context, Processor processor, ProcessorDefinition<?> definition) throws MalformedObjectNameException {
105            StringBuffer buffer = new StringBuffer();
106            buffer.append(domainName).append(":");
107            buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(",");
108            buffer.append(KEY_TYPE + "=").append(TYPE_PROCESSOR).append(",");
109    
110            if (definition.hasCustomIdAssigned()) {
111                // use id in name
112                String nodeId = definition.getId();
113                buffer.append(KEY_NAME + "=").append(ObjectName.quote(nodeId));
114            } else {
115                // create a name based on its instance
116                buffer.append(KEY_NAME + "=")
117                    .append(processor.getClass().getSimpleName())
118                    .append("(").append(ObjectHelper.getIdentityHashCode(processor)).append(")");
119            }
120            return createObjectName(buffer);
121        }
122    
123        public ObjectName getObjectNameForErrorHandler(RouteContext routeContext, Processor errorHandler, ErrorHandlerBuilder builder) throws MalformedObjectNameException {
124            StringBuffer buffer = new StringBuffer();
125            buffer.append(domainName).append(":");
126            buffer.append(KEY_CONTEXT + "=").append(getContextId(routeContext.getCamelContext())).append(",");
127            buffer.append(KEY_TYPE + "=").append(TYPE_ERRORHANDLER).append(",");
128    
129            // we want to only register one instance of the various error handler types and thus do some lookup
130            // if its a ErrorHandlerBuildRef. We need a bit of work to do that as there are potential indirection.
131            String ref = null;
132            if (builder instanceof ErrorHandlerBuilderRef) {
133                ErrorHandlerBuilderRef builderRef = (ErrorHandlerBuilderRef) builder;
134    
135                // it has not then its an indirection and we should do some work to lookup the real builder
136                ref = builderRef.getRef();
137                builder = ErrorHandlerBuilderRef.lookupErrorHandlerBuilder(routeContext, builderRef.getRef());
138    
139                // must do a 2nd lookup in case this is also a reference
140                // (this happens with spring DSL using errorHandlerRef on <route> as it gets a bit
141                // complex with indirections for error handler references
142                if (builder instanceof ErrorHandlerBuilderRef) {
143                    builderRef = (ErrorHandlerBuilderRef) builder;
144                    // does it refer to a non default error handler then do a 2nd lookup
145                    if (!builderRef.getRef().equals(ErrorHandlerBuilderRef.DEFAULT_ERROR_HANDLER_BUILDER)) {
146                        builder = ErrorHandlerBuilderRef.lookupErrorHandlerBuilder(routeContext, builderRef.getRef());
147                        ref = builderRef.getRef();
148                    }
149                }
150            }
151    
152            if (ref != null) {
153                String name = builder.getClass().getSimpleName() + "(ref:" + ref + ")";
154                buffer.append(KEY_NAME + "=").append(ObjectName.quote(name));
155            } else {
156                // create a name based on its instance
157                buffer.append(KEY_NAME + "=")
158                    .append(builder.getClass().getSimpleName())
159                    .append("(").append(ObjectHelper.getIdentityHashCode(builder)).append(")");
160            }
161    
162            return createObjectName(buffer);
163        }
164    
165        public ObjectName getObjectNameForConsumer(CamelContext context, Consumer consumer) throws MalformedObjectNameException {
166            StringBuffer buffer = new StringBuffer();
167            buffer.append(domainName).append(":");
168            buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(",");
169            buffer.append(KEY_TYPE + "=").append(TYPE_CONSUMER).append(",");
170    
171            String name = consumer.getClass().getSimpleName();
172            if (ObjectHelper.isEmpty(name)) {
173                name = "Consumer";
174            }
175            buffer.append(KEY_NAME + "=")
176                .append(name)
177                .append("(").append(ObjectHelper.getIdentityHashCode(consumer)).append(")");
178            return createObjectName(buffer);
179        }
180    
181        public ObjectName getObjectNameForProducer(CamelContext context, Producer producer) throws MalformedObjectNameException {
182            StringBuffer buffer = new StringBuffer();
183            buffer.append(domainName).append(":");
184            buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(",");
185            buffer.append(KEY_TYPE + "=").append(TYPE_PRODUCER).append(",");
186    
187            String name = producer.getClass().getSimpleName();
188            if (ObjectHelper.isEmpty(name)) {
189                name = "Producer";
190            }
191            buffer.append(KEY_NAME + "=")
192                .append(name)
193                .append("(").append(ObjectHelper.getIdentityHashCode(producer)).append(")");
194            return createObjectName(buffer);
195        }
196    
197        public ObjectName getObjectNameForTracer(CamelContext context, InterceptStrategy tracer) throws MalformedObjectNameException {
198            StringBuffer buffer = new StringBuffer();
199            buffer.append(domainName).append(":");
200            buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(",");
201            buffer.append(KEY_TYPE + "=" + TYPE_TRACER + ",");
202            buffer.append(KEY_NAME + "=")
203                .append("Tracer")
204                .append("(").append(ObjectHelper.getIdentityHashCode(tracer)).append(")");
205            return createObjectName(buffer);
206        }
207    
208        public ObjectName getObjectNameForRoute(Route route) throws MalformedObjectNameException {
209            Endpoint ep = route.getEndpoint();
210            String id = route.getId();
211    
212            StringBuffer buffer = new StringBuffer();
213            buffer.append(domainName).append(":");
214            buffer.append(KEY_CONTEXT + "=").append(getContextId(ep.getCamelContext())).append(",");
215            buffer.append(KEY_TYPE + "=" + TYPE_ROUTE + ",");
216            buffer.append(KEY_NAME + "=").append(ObjectName.quote(id));
217            return createObjectName(buffer);
218        }
219    
220        public ObjectName getObjectNameForService(CamelContext context, Service service) throws MalformedObjectNameException {
221            StringBuffer buffer = new StringBuffer();
222            buffer.append(domainName).append(":");
223            buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(",");
224            buffer.append(KEY_TYPE + "=" + TYPE_SERVICE + ",");
225            buffer.append(KEY_NAME + "=")
226                .append(service.getClass().getSimpleName())
227                .append("(").append(ObjectHelper.getIdentityHashCode(service)).append(")");
228            return createObjectName(buffer);
229        }
230    
231        public String getDomainName() {
232            return domainName;
233        }
234    
235        public void setDomainName(String domainName) {
236            this.domainName = domainName;
237        }
238    
239        public String getHostName() {
240            return hostName;
241        }
242    
243        public void setHostName(String hostName) {
244            this.hostName = hostName;
245        }
246    
247        protected String getContextId(CamelContext context) {
248            return hostName + "/" + (context != null ? context.getName() : VALUE_UNKNOWN);
249        }
250    
251        protected String getEndpointId(Endpoint ep) {
252            if (ep.isSingleton()) {
253                return ep.getEndpointKey();
254            } else {
255                // non singleton then add hashcoded id
256                String uri = ep.getEndpointKey();
257                int pos = uri.indexOf('?');
258                String id = (pos == -1) ? uri : uri.substring(0, pos);
259                id += "?id=" + ObjectHelper.getIdentityHashCode(ep);
260                return id;
261            }
262        }
263    
264        /**
265         * Factory method to create an ObjectName escaping any required characters
266         */
267        protected ObjectName createObjectName(StringBuffer buffer) throws MalformedObjectNameException {
268            String text = buffer.toString();
269            try {
270                return new ObjectName(text);
271            } catch (MalformedObjectNameException e) {
272                throw new MalformedObjectNameException("Could not create ObjectName from: " + text + ". Reason: " + e);
273            }
274        }
275    }