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