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.Route;
029    import org.apache.camel.Service;
030    import org.apache.camel.model.ProcessorDefinition;
031    import org.apache.camel.spi.RouteContext;
032    
033    /**
034     * Naming strategy used when registering MBeans.
035     */
036    public class CamelNamingStrategy {
037        public static final String VALUE_UNKNOWN = "unknown";
038        public static final String KEY_NAME = "name";
039        public static final String KEY_TYPE = "type";
040        public static final String KEY_CONTEXT = "context";
041        public static final String KEY_GROUP = "group";
042        public static final String KEY_ROUTE = "route";
043        public static final String KEY_NODE_ID = "nodeid";
044        public static final String TYPE_CONTEXT = "context";
045        public static final String TYPE_ENDPOINT = "endpoints";
046        public static final String TYPE_PROCESSOR = "processors";
047        public static final String TYPE_CONSUMER = "consumers";
048        public static final String TYPE_ROUTE = "routes";
049    
050        protected String domainName;
051        protected String hostName = "localhost";
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 can be thrown
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_NAME + "=").append("context");
082            return createObjectName(buffer);
083        }
084    
085        /**
086         * Implements the naming strategy for a {@link ManagedEndpoint}.
087         * The convention used for a {@link ManagedEndpoint} ObjectName is:
088         * <tt>&lt;domain&gt;:context=&lt;context-name&gt;,type=endpoint,component=&lt;component-name&gt;name=&lt;endpoint-name&gt;</tt>
089         */
090        public ObjectName getObjectName(ManagedEndpoint mbean) throws MalformedObjectNameException {
091            Endpoint ep = mbean.getEndpoint();
092    
093            StringBuffer buffer = new StringBuffer();
094            buffer.append(domainName).append(":");
095            buffer.append(KEY_CONTEXT + "=").append(getContextId(ep.getCamelContext())).append(",");
096            buffer.append(KEY_TYPE + "=" + TYPE_ENDPOINT + ",");
097            buffer.append(KEY_NAME + "=").append(ObjectName.quote(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            String serviceBranch;
108            Service service = mbean.getService();
109            if (service instanceof Consumer) {
110                serviceBranch = TYPE_CONSUMER;
111            } else {
112                return null;
113            }
114    
115            StringBuffer buffer = new StringBuffer();
116            buffer.append(domainName).append(":");
117            buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(",");
118            buffer.append(KEY_TYPE + "=" + serviceBranch + ",");
119            buffer.append(KEY_NAME + "=")
120                .append(service.getClass().getSimpleName())
121                .append("(0x").append(Integer.toHexString(mbean.getService().hashCode())).append(")");
122            return createObjectName(buffer);
123        }
124    
125    
126        /**
127         * Implements the naming strategy for a {@link ManagedRoute}.
128         * The convention used for a {@link ManagedRoute} ObjectName is:
129         * <tt>&lt;domain&gt;:context=&lt;context-name&gt;,route=&lt;route-name&gt;,type=route,name=&lt;route-name&gt;</tt>
130         */
131        public ObjectName getObjectName(ManagedRoute mbean) throws MalformedObjectNameException {
132            Route route = mbean.getRoute();
133            Endpoint ep = route.getEndpoint();
134            String id = (String)route.getProperties().get(Route.ID_PROPERTY);
135    
136            StringBuffer buffer = new StringBuffer();
137            buffer.append(domainName).append(":");
138            buffer.append(KEY_CONTEXT + "=").append(getContextId(ep.getCamelContext())).append(",");
139            buffer.append(KEY_TYPE + "=" + TYPE_ROUTE + ",");
140            buffer.append(KEY_NAME + "=").append(ObjectName.quote(id == null ? ("0x" + Integer.toHexString(route.hashCode())) : id));
141            return createObjectName(buffer);
142        }
143    
144        /**
145         * Implements the naming strategy for a {@link ProcessorDefinition}.
146         * The convention used for a {@link ProcessorDefinition} ObjectName is:
147         * <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>
148         */
149        public ObjectName getObjectName(RouteContext routeContext, ProcessorDefinition processor)
150            throws MalformedObjectNameException {
151            Endpoint ep = routeContext.getEndpoint();
152            String ctxid;
153            String cid;
154            if (ep != null) {
155                ctxid = getContextId(ep.getCamelContext());            
156                cid = ObjectName.quote(ep.getEndpointUri());
157            } else {
158                ctxid = VALUE_UNKNOWN;
159                cid = null;
160            }
161            //String id = VALUE_UNKNOWN.equals(cid) ? ObjectName.quote(getEndpointId(ep) : "[" + cid + "]" + ObjectName.quote(getEndpointId(ep);
162            String nodeId = processor.idOrCreate();
163    
164            StringBuffer buffer = new StringBuffer();
165            buffer.append(domainName).append(":");
166            buffer.append(KEY_CONTEXT + "=").append(ctxid).append(",");
167            // buffer.append(KEY_ROUTE + "=").append(id).append(",");
168            buffer.append(KEY_TYPE + "=" + TYPE_PROCESSOR + ",");
169            buffer.append(KEY_NODE_ID + "=").append(nodeId).append(",");
170            buffer.append(KEY_NAME + "=").append(ObjectName.quote(processor.toString()));
171            return createObjectName(buffer);
172        }
173    
174        public String getDomainName() {
175            return domainName;
176        }
177    
178        public void setDomainName(String domainName) {
179            this.domainName = domainName;
180        }
181    
182        public String getHostName() {
183            return hostName;
184        }
185    
186        public void setHostName(String hostName) {
187            this.hostName = hostName;
188        }
189    
190        protected String getContextId(CamelContext context) {
191            return hostName + "/" + (context != null ? context.getName() : VALUE_UNKNOWN);
192        }
193    
194        protected String getEndpointId(Endpoint ep) {
195            if (ep.isSingleton()) {
196                return ep.getEndpointKey();
197            } else {
198                // non singleton then add hashcoded id
199                String uri = ep.getEndpointKey();
200                int pos = uri.indexOf('?');
201                String id = (pos == -1) ? uri : uri.substring(0, pos);
202                id += "?id=0x" + Integer.toHexString(ep.hashCode());
203                return id;
204            }
205        }
206    
207        /**
208         * Factory method to create an ObjectName escaping any required characters
209         */
210        protected ObjectName createObjectName(StringBuffer buffer) throws MalformedObjectNameException {
211            String text = buffer.toString();
212            try {
213                return new ObjectName(text);
214            } catch (MalformedObjectNameException e) {
215                throw new MalformedObjectNameException("Could not create ObjectName from: " + text + ". Reason: " + e);
216            }
217        }
218    }