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.mbean;
018    
019    import java.io.InputStream;
020    import java.util.Collection;
021    import java.util.LinkedHashSet;
022    import java.util.List;
023    import java.util.Map;
024    import java.util.Properties;
025    import java.util.Set;
026    import java.util.concurrent.TimeUnit;
027    import javax.management.MBeanServer;
028    import javax.management.MBeanServerInvocationHandler;
029    import javax.management.ObjectName;
030    
031    import org.apache.camel.CamelContext;
032    import org.apache.camel.Endpoint;
033    import org.apache.camel.ManagementStatisticsLevel;
034    import org.apache.camel.ProducerTemplate;
035    import org.apache.camel.TimerListener;
036    import org.apache.camel.api.management.ManagedResource;
037    import org.apache.camel.api.management.mbean.ManagedCamelContextMBean;
038    import org.apache.camel.api.management.mbean.ManagedProcessorMBean;
039    import org.apache.camel.api.management.mbean.ManagedRouteMBean;
040    import org.apache.camel.model.ModelCamelContext;
041    import org.apache.camel.model.ModelHelper;
042    import org.apache.camel.model.RouteDefinition;
043    import org.apache.camel.model.RoutesDefinition;
044    import org.apache.camel.util.CamelContextHelper;
045    
046    /**
047     * @version 
048     */
049    @ManagedResource(description = "Managed CamelContext")
050    public class ManagedCamelContext extends ManagedPerformanceCounter implements TimerListener, ManagedCamelContextMBean {
051        private final ModelCamelContext context;   
052        private final LoadTriplet load = new LoadTriplet();
053    
054        public ManagedCamelContext(ModelCamelContext context) {
055            this.context = context;
056            boolean enabled = context.getManagementStrategy().getStatisticsLevel() != ManagementStatisticsLevel.Off;
057            setStatisticsEnabled(enabled);
058        }
059    
060        public CamelContext getContext() {
061            return context;
062        }
063    
064        public String getCamelId() {
065            return context.getName();
066        }
067    
068        public String getManagementName() {
069            return context.getManagementName();
070        }
071    
072        public String getCamelVersion() {
073            return context.getVersion();
074        }
075    
076        public String getState() {
077            return context.getStatus().name();
078        }
079    
080        public String getUptime() {
081            return context.getUptime();
082        }
083    
084        public Map<String, String> getProperties() {
085            if (context.getProperties().isEmpty()) {
086                return null;
087            }
088            return context.getProperties();
089        }
090        
091        public Boolean getTracing() {
092            return context.isTracing();
093        }
094    
095        public void setTracing(Boolean tracing) {
096            context.setTracing(tracing);
097        }
098    
099        public Integer getInflightExchanges() {
100            return context.getInflightRepository().size();
101        }
102    
103        public void setTimeout(long timeout) {
104            context.getShutdownStrategy().setTimeout(timeout);
105        }
106    
107        public long getTimeout() {
108            return context.getShutdownStrategy().getTimeout();
109        }
110    
111        public void setTimeUnit(TimeUnit timeUnit) {
112            context.getShutdownStrategy().setTimeUnit(timeUnit);
113        }
114    
115        public TimeUnit getTimeUnit() {
116            return context.getShutdownStrategy().getTimeUnit();
117        }
118    
119        public void setShutdownNowOnTimeout(boolean shutdownNowOnTimeout) {
120            context.getShutdownStrategy().setShutdownNowOnTimeout(shutdownNowOnTimeout);
121        }
122    
123        public boolean isShutdownNowOnTimeout() {
124            return context.getShutdownStrategy().isShutdownNowOnTimeout();
125        }
126        
127        public String getLoad01() {
128            return String.format("%.2f", load.getLoad1());
129        }
130    
131        public String getLoad05() {
132            return String.format("%.2f", load.getLoad5());
133        }
134    
135        public String getLoad15() {
136            return String.format("%.2f", load.getLoad15());
137        }
138    
139        public void onTimer() {
140            load.update(getInflightExchanges());
141        }
142    
143        public void start() throws Exception {
144            if (context.isSuspended()) {
145                context.resume();
146            } else {
147                context.start();
148            }
149        }
150    
151        public void stop() throws Exception {
152            context.stop();
153        }
154    
155        public void suspend() throws Exception {
156            context.suspend();
157        }
158    
159        public void resume() throws Exception {
160            if (context.isSuspended()) {
161                context.resume();
162            } else {
163                throw new IllegalStateException("CamelContext is not suspended");
164            }
165        }
166    
167        public void sendBody(String endpointUri, Object body) throws Exception {
168            ProducerTemplate template = context.createProducerTemplate();
169            try {
170                template.sendBody(endpointUri, body);
171            } finally {
172                template.stop();
173            }
174        }
175    
176        public void sendStringBody(String endpointUri, String body) throws Exception {
177            sendBody(endpointUri, body);
178        }
179    
180        public void sendBodyAndHeaders(String endpointUri, Object body, Map<String, Object> headers) throws Exception {
181            ProducerTemplate template = context.createProducerTemplate();
182            try {
183                template.sendBodyAndHeaders(endpointUri, body, headers);
184            } finally {
185                template.stop();
186            }
187        }
188    
189        public Object requestBody(String endpointUri, Object body) throws Exception {
190            ProducerTemplate template = context.createProducerTemplate();
191            Object answer = null;
192            try {
193                answer = template.requestBody(endpointUri, body);
194            } finally {
195                template.stop();
196            }
197            return answer;
198        }
199    
200        public Object requestStringBody(String endpointUri, String body) throws Exception {
201            return requestBody(endpointUri, body);
202        }
203    
204        public Object requestBodyAndHeaders(String endpointUri, Object body, Map<String, Object> headers) throws Exception {
205            ProducerTemplate template = context.createProducerTemplate();
206            Object answer = null;
207            try {
208                answer = template.requestBodyAndHeaders(endpointUri, body, headers);
209            } finally {
210                template.stop();
211            }
212            return answer;
213        }
214    
215        public String dumpRoutesAsXml() throws Exception {
216            List<RouteDefinition> routes = context.getRouteDefinitions();
217            if (routes.isEmpty()) {
218                return null;
219            }
220    
221            // use a routes definition to dump the routes
222            RoutesDefinition def = new RoutesDefinition();
223            def.setRoutes(routes);
224            return ModelHelper.dumpModelAsXml(def);
225        }
226    
227        public void addOrUpdateRoutesFromXml(String xml) throws Exception {
228            // convert to model from xml
229            InputStream is = context.getTypeConverter().mandatoryConvertTo(InputStream.class, xml);
230            RoutesDefinition def = context.loadRoutesDefinition(is);
231            if (def == null) {
232                return;
233            }
234    
235            // add will remove existing route first
236            context.addRouteDefinitions(def.getRoutes());
237        }
238    
239        public String dumpRoutesStatsAsXml(boolean fullStats, boolean includeProcessors) throws Exception {
240            StringBuilder sb = new StringBuilder();
241            sb.append("<camelContextStat").append(String.format(" id=\"%s\"", getCamelId()));
242            // use substring as we only want the attributes
243            String stat = dumpStatsAsXml(fullStats);
244            sb.append(" ").append(stat.substring(7, stat.length() - 2)).append(">\n");
245    
246            MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer();
247            if (server != null) {
248                // gather all the routes for this CamelContext, which requires JMX
249                ObjectName query = ObjectName.getInstance("org.apache.camel:context=*/" + getContext().getManagementName() + ",type=routes,*");
250                Set<ObjectName> routes = server.queryNames(query, null);
251    
252                Set<ManagedProcessorMBean> processors = new LinkedHashSet<ManagedProcessorMBean>();
253                if (includeProcessors) {
254                    // gather all the processors for this CamelContext, which requires JMX
255                    query = ObjectName.getInstance("org.apache.camel:context=*/" + getContext().getManagementName() + ",type=processors,*");
256                    Set<ObjectName> names = server.queryNames(query, null);
257                    for (ObjectName on : names) {
258                        ManagedProcessorMBean processor = MBeanServerInvocationHandler.newProxyInstance(server, on, ManagedProcessorMBean.class, true);
259                        processors.add(processor);
260                    }
261                }
262                
263                // loop the routes, and append the processor stats if needed
264                sb.append("  <routeStats>\n");
265                for (ObjectName on : routes) {
266                    ManagedRouteMBean route = MBeanServerInvocationHandler.newProxyInstance(server, on, ManagedRouteMBean.class, true);
267                    sb.append("    <routeStat").append(String.format(" id=\"%s\"", route.getRouteId()));
268                    // use substring as we only want the attributes
269                    stat = route.dumpStatsAsXml(fullStats);
270                    sb.append(" ").append(stat.substring(7, stat.length() - 2)).append(">\n");
271    
272                    // add processor details if needed
273                    if (includeProcessors) {
274                        sb.append("      <processorStats>\n");
275                        for (ManagedProcessorMBean processor : processors) {
276                            // the processor must belong to this route
277                            if (route.getRouteId().equals(processor.getRouteId())) {
278                                sb.append("        <processorStat").append(String.format(" id=\"%s\"", processor.getProcessorId()));
279                                // use substring as we only want the attributes
280                                sb.append(" ").append(processor.dumpStatsAsXml(fullStats).substring(7)).append("\n");
281                            }
282                        }
283                        sb.append("      </processorStats>\n");
284                    }
285                    sb.append("    </routeStat>\n");
286                }
287                sb.append("  </routeStats>\n");
288            }
289    
290            sb.append("</camelContextStat>");
291            return sb.toString();
292        }
293    
294        public boolean createEndpoint(String uri) throws Exception {
295            if (context.hasEndpoint(uri) != null) {
296                // endpoint already exists
297                return false;
298            }
299    
300            Endpoint endpoint = context.getEndpoint(uri);
301            if (endpoint != null) {
302                // ensure endpoint is registered, as the management strategy could have been configured to not always
303                // register new endpoints in JMX, so we need to check if its registered, and if not register it manually
304                ObjectName on = context.getManagementStrategy().getManagementNamingStrategy().getObjectNameForEndpoint(endpoint);
305                if (on != null && !context.getManagementStrategy().getManagementAgent().isRegistered(on)) {
306                    // register endpoint as mbean
307                    Object me = context.getManagementStrategy().getManagementObjectStrategy().getManagedObjectForEndpoint(context, endpoint);
308                    context.getManagementStrategy().getManagementAgent().register(me, on);
309                }
310                return true;
311            } else {
312                return false;
313            }
314        }
315    
316        public int removeEndpoints(String pattern) throws Exception {
317            // endpoints is always removed from JMX if removed from context
318            Collection<Endpoint> removed = context.removeEndpoints(pattern);
319            return removed.size();
320        }
321    
322        public Map<String, Properties> findComponents() throws Exception {
323            return CamelContextHelper.findComponents(context);
324        }
325    
326    }