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    public class CamelNamingStrategy {
033        public static final String VALUE_UNKNOWN = "unknown";
034        public static final String KEY_NAME = "name";
035        public static final String KEY_TYPE = "type";
036        public static final String KEY_CONTEXT = "context";
037        public static final String KEY_GROUP = "group";
038        public static final String KEY_COMPONENT = "component";
039        public static final String KEY_ROUTE = "route";
040        public static final String TYPE_CONTEXT = "context";
041        public static final String TYPE_ENDPOINT = "endpoint";
042        public static final String TYPE_PROCESSOR = "processor";
043        public static final String TYPE_ROUTE = "route";
044        public static final String TYPE_SERVICE = "service";
045        public static final String KEY_NODE_ID = "nodeid";
046        public static final String KEY_INSTANCE = "instance";
047    
048        protected String domainName;
049        protected String hostName = "locahost";
050    
051        public CamelNamingStrategy() {
052            this("org.apache.camel");
053        }
054    
055        public CamelNamingStrategy(String domainName) {
056            if (domainName != null) {
057                this.domainName = domainName;
058            }
059            try {
060                hostName = InetAddress.getLocalHost().getHostName();
061            } catch (UnknownHostException ex) {
062                // ignore, use the default "locahost"
063            }
064        }
065    
066        /**
067         * Implements the naming strategy for a {@link CamelContext}.
068         * The convention used for a {@link CamelContext} ObjectName is:
069         * <tt>&lt;domain&gt;:context=&lt;context-name&gt;,type=context,name=&lt;context-name&gt;</tt>
070         *
071         * @param context the camel context
072         * @return generated ObjectName
073         * @throws MalformedObjectNameException
074         */
075        public ObjectName getObjectName(CamelContext context) throws MalformedObjectNameException {
076            StringBuffer buffer = new StringBuffer();
077            buffer.append(domainName).append(":");
078            buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(",");
079            buffer.append(KEY_TYPE + "=" + TYPE_CONTEXT + ",");
080            buffer.append(KEY_NAME + "=").append(getContextId(context));
081            return createObjectName(buffer);
082        }
083    
084        /**
085         * Implements the naming strategy for a {@link ManagedEndpoint}.
086         * The convention used for a {@link ManagedEndpoint} ObjectName is:
087         * <tt>&lt;domain&gt;:context=&lt;context-name&gt;,type=endpoint,component=&lt;component-name&gt;name=&lt;endpoint-name&gt;</tt>
088         */
089        public ObjectName getObjectName(ManagedEndpoint mbean) throws MalformedObjectNameException {
090            Endpoint<? extends Exchange> ep = mbean.getEndpoint();
091    
092            StringBuffer buffer = new StringBuffer();
093            buffer.append(domainName).append(":");
094            buffer.append(KEY_CONTEXT + "=").append(getContextId(ep.getCamelContext())).append(",");
095            buffer.append(KEY_TYPE + "=" + TYPE_ENDPOINT + ",");
096            buffer.append(KEY_COMPONENT + "=").append(getComponentId(ep)).append(",");
097            buffer.append(KEY_NAME + "=").append(getEndpointId(ep));
098            return createObjectName(buffer);
099        }
100    
101        /**
102         * Implements the naming strategy for a {@link org.apache.camel.impl.ServiceSupport Service}.
103         * The convention used for a {@link org.apache.camel.Service Service} ObjectName is
104         * <tt>&lt;domain&gt;:context=&lt;context-name&gt;,type=service,name=&lt;service-name&gt;</tt>
105         */
106        public ObjectName getObjectName(CamelContext context, ManagedService mbean) throws MalformedObjectNameException {
107            StringBuffer buffer = new StringBuffer();
108            buffer.append(domainName).append(":");
109            buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(",");
110            buffer.append(KEY_TYPE + "=" + TYPE_SERVICE + ",");
111            buffer.append(KEY_NAME + "=").append(Integer.toHexString(mbean.getService().hashCode()));
112            return createObjectName(buffer);
113        }
114    
115    
116        /**
117         * Implements the naming strategy for a {@link ManagedRoute}.
118         * The convention used for a {@link ManagedRoute} ObjectName is:
119         * <tt>&lt;domain&gt;:context=&lt;context-name&gt;,route=&lt;route-name&gt;,type=route,name=&lt;route-name&gt;</tt>
120         */
121        public ObjectName getObjectName(ManagedRoute mbean) throws MalformedObjectNameException {
122            Route<? extends Exchange> route = mbean.getRoute();
123            Endpoint<? extends Exchange> ep = route.getEndpoint();
124    
125            String ctxid = ep != null ? getContextId(ep.getCamelContext()) : VALUE_UNKNOWN;
126            String cid = getComponentId(ep);
127            String id = VALUE_UNKNOWN.equals(cid) ? getEndpointId(ep)
128                : "[" + cid + "]" + getEndpointId(ep);
129    
130            StringBuffer buffer = new StringBuffer();
131            buffer.append(domainName).append(":");
132            buffer.append(KEY_CONTEXT + "=").append(ctxid).append(",");
133            buffer.append(KEY_ROUTE + "=").append(id).append(",");
134            buffer.append(KEY_TYPE + "=" + TYPE_ROUTE + ",");
135            buffer.append(KEY_NAME + "=").append(id);
136            return createObjectName(buffer);
137        }
138    
139        /**
140         * Implements the naming strategy for a {@link ProcessorType}.
141         * The convention used for a {@link ProcessorType} ObjectName is:
142         * <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;,instance=&lt;instance-id&gt;</tt>
143         */
144        public ObjectName getObjectName(RouteContext routeContext, 
145                ProcessorType processor, Integer instanceCount) throws MalformedObjectNameException {
146            Endpoint<? extends Exchange> ep = routeContext.getEndpoint();
147            String ctxid = ep != null ? getContextId(ep.getCamelContext()) : VALUE_UNKNOWN;
148            String cid = getComponentId(ep);
149            String id = VALUE_UNKNOWN.equals(cid) ? getEndpointId(ep) : "[" + cid + "]" + getEndpointId(ep);
150    
151            StringBuffer buffer = new StringBuffer();
152            buffer.append(domainName).append(":");
153            buffer.append(KEY_CONTEXT + "=").append(ctxid).append(",");
154            buffer.append(KEY_ROUTE + "=").append(id).append(",");
155            buffer.append(KEY_TYPE + "=" + TYPE_PROCESSOR + ",");
156            buffer.append(KEY_NODE_ID + "=" + processor.getId() + ",");
157            if (instanceCount != null) {
158                buffer.append(KEY_INSTANCE + "=" + instanceCount + ",");
159            }
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    }