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    
022    import javax.management.MalformedObjectNameException;
023    import javax.management.ObjectName;
024    
025    import org.apache.camel.CamelContext;
026    import org.apache.camel.Endpoint;
027    import org.apache.camel.Exchange;
028    import org.apache.camel.Route;
029    import org.apache.camel.model.ProcessorType;
030    import org.apache.camel.spi.RouteContext;
031    
032    /**
033     * Naming strategy used when registering MBeans.
034     */
035    public class CamelNamingStrategy {
036        public static final String VALUE_UNKNOWN = "unknown";
037        public static final String KEY_NAME = "name";
038        public static final String KEY_TYPE = "type";
039        public static final String KEY_CONTEXT = "context";
040        public static final String KEY_GROUP = "group";
041        public static final String KEY_COMPONENT = "component";
042        public static final String KEY_ROUTE = "route";
043        public static final String TYPE_CONTEXT = "context";
044        public static final String TYPE_ENDPOINT = "endpoint";
045        public static final String TYPE_PROCESSOR = "processor";
046        public static final String TYPE_ROUTE = "route";
047        public static final String TYPE_SERVICE = "service";
048        public static final String KEY_NODE_ID = "nodeid";
049    
050        protected String domainName;
051        protected String hostName = "locahost";
052    
053        public CamelNamingStrategy() {
054            this("org.apache.camel");
055        }
056    
057        public CamelNamingStrategy(String domainName) {
058            if (domainName != null) {
059                this.domainName = domainName;
060            }
061            try {
062                hostName = InetAddress.getLocalHost().getHostName();
063            } catch (UnknownHostException ex) {
064                // ignore, use the default "locahost"
065            }
066        }
067    
068        /**
069         * Implements the naming strategy for a {@link CamelContext}.
070         * The convention used for a {@link CamelContext} ObjectName is:
071         * <tt>&lt;domain&gt;:context=&lt;context-name&gt;,type=context,name=&lt;context-name&gt;</tt>
072         *
073         * @param context the camel context
074         * @return generated ObjectName
075         * @throws MalformedObjectNameException
076         */
077        public ObjectName getObjectName(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(getContextId(context));
083            return createObjectName(buffer);
084        }
085    
086        /**
087         * Implements the naming strategy for a {@link ManagedEndpoint}.
088         * The convention used for a {@link ManagedEndpoint} ObjectName is:
089         * <tt>&lt;domain&gt;:context=&lt;context-name&gt;,type=endpoint,component=&lt;component-name&gt;name=&lt;endpoint-name&gt;</tt>
090         */
091        public ObjectName getObjectName(ManagedEndpoint mbean) throws MalformedObjectNameException {
092            Endpoint<? extends Exchange> ep = mbean.getEndpoint();
093    
094            StringBuffer buffer = new StringBuffer();
095            buffer.append(domainName).append(":");
096            buffer.append(KEY_CONTEXT + "=").append(getContextId(ep.getCamelContext())).append(",");
097            buffer.append(KEY_TYPE + "=" + TYPE_ENDPOINT + ",");
098            buffer.append(KEY_COMPONENT + "=").append(getComponentId(ep)).append(",");
099            buffer.append(KEY_NAME + "=").append(getEndpointId(ep));
100            return createObjectName(buffer);
101        }
102    
103        /**
104         * Implements the naming strategy for a {@link org.apache.camel.impl.ServiceSupport Service}.
105         * The convention used for a {@link org.apache.camel.Service Service} ObjectName is
106         * <tt>&lt;domain&gt;:context=&lt;context-name&gt;,type=service,name=&lt;service-name&gt;</tt>
107         */
108        public ObjectName getObjectName(CamelContext context, ManagedService mbean) throws MalformedObjectNameException {
109            StringBuffer buffer = new StringBuffer();
110            buffer.append(domainName).append(":");
111            buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(",");
112            buffer.append(KEY_TYPE + "=" + TYPE_SERVICE + ",");
113            buffer.append(KEY_NAME + "=").append(Integer.toHexString(mbean.getService().hashCode()));
114            return createObjectName(buffer);
115        }
116    
117    
118        /**
119         * Implements the naming strategy for a {@link ManagedRoute}.
120         * The convention used for a {@link ManagedRoute} ObjectName is:
121         * <tt>&lt;domain&gt;:context=&lt;context-name&gt;,route=&lt;route-name&gt;,type=route,name=&lt;route-name&gt;</tt>
122         */
123        public ObjectName getObjectName(ManagedRoute mbean) throws MalformedObjectNameException {
124            Route<? extends Exchange> route = mbean.getRoute();
125            Endpoint<? extends Exchange> ep = route.getEndpoint();
126    
127            String ctxid = ep != null ? getContextId(ep.getCamelContext()) : VALUE_UNKNOWN;
128            String cid = getComponentId(ep);
129            String id = VALUE_UNKNOWN.equals(cid) ? getEndpointId(ep)
130                : "[" + cid + "]" + getEndpointId(ep);
131    
132            StringBuffer buffer = new StringBuffer();
133            buffer.append(domainName).append(":");
134            buffer.append(KEY_CONTEXT + "=").append(ctxid).append(",");
135            buffer.append(KEY_ROUTE + "=").append(id).append(",");
136            buffer.append(KEY_TYPE + "=" + TYPE_ROUTE + ",");
137            buffer.append(KEY_NAME + "=").append(id);
138            return createObjectName(buffer);
139        }
140    
141        /**
142         * Implements the naming strategy for a {@link ProcessorType}.
143         * The convention used for a {@link ProcessorType} ObjectName is:
144         * <tt>&lt;domain&gt;:context=&lt;context-name&gt;,route=&lt;route-name&gt;,type=processor,name=&lt;processor-name&gt;,nodeid=&lt;node-id&gt;</tt>
145         */
146        public ObjectName getObjectName(RouteContext routeContext, ProcessorType processor)
147            throws MalformedObjectNameException {
148            Endpoint<? extends Exchange> ep = routeContext.getEndpoint();
149            String ctxid = ep != null ? getContextId(ep.getCamelContext()) : VALUE_UNKNOWN;
150            String cid = getComponentId(ep);
151            String id = VALUE_UNKNOWN.equals(cid) ? getEndpointId(ep) : "[" + cid + "]" + getEndpointId(ep);
152            String nodeId = processor.idOrCreate();
153    
154            StringBuffer buffer = new StringBuffer();
155            buffer.append(domainName).append(":");
156            buffer.append(KEY_CONTEXT + "=").append(ctxid).append(",");
157            buffer.append(KEY_ROUTE + "=").append(id).append(",");
158            buffer.append(KEY_TYPE + "=" + TYPE_PROCESSOR + ",");
159            buffer.append(KEY_NODE_ID + "=").append(nodeId).append(",");
160            buffer.append(KEY_NAME + "=").append(ObjectName.quote(processor.toString()));
161            return createObjectName(buffer);
162        }
163    
164        public String getDomainName() {
165            return domainName;
166        }
167    
168        public void setDomainName(String domainName) {
169            this.domainName = domainName;
170        }
171    
172        public String getHostName() {
173            return hostName;
174        }
175    
176        public void setHostName(String hostName) {
177            this.hostName = hostName;
178        }
179    
180        protected String getContextId(CamelContext context) {
181            String id = context != null ? context.getName() : VALUE_UNKNOWN;
182            return hostName + "/" + id;
183        }
184    
185        protected String getComponentId(Endpoint<? extends Exchange> ep) {
186            String uri = ep.getEndpointUri();
187            int pos = uri.indexOf(':');
188            return (pos == -1) ? VALUE_UNKNOWN : uri.substring(0, pos);
189        }
190    
191        protected String getEndpointId(Endpoint<? extends Exchange> ep) {
192            String uri = ep.getEndpointUri();
193            int pos = uri.indexOf(':');
194            String id = (pos == -1) ? uri : uri.substring(pos + 1);
195            if (!ep.isSingleton()) {
196                id += "@" + Integer.toString(ep.hashCode());
197            }
198            return ObjectNameEncoder.encode(id);
199        }
200    
201        /**
202         * Factory method to create an ObjectName escaping any required characters
203         */
204        protected ObjectName createObjectName(StringBuffer buffer) throws MalformedObjectNameException {
205            String text = buffer.toString();
206            try {
207                return new ObjectName(text);
208            } catch (MalformedObjectNameException e) {
209                throw new MalformedObjectNameException("Could not create ObjectName from: " + text + ". Reason: " + e);
210            }
211        }
212    }