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 }