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