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.Set;
025 import java.util.concurrent.TimeUnit;
026
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
045 /**
046 * @version
047 */
048 @ManagedResource(description = "Managed CamelContext")
049 public class ManagedCamelContext extends ManagedPerformanceCounter implements TimerListener, ManagedCamelContextMBean {
050 private final ModelCamelContext context;
051 private final LoadTriplet load = new LoadTriplet();
052
053 public ManagedCamelContext(ModelCamelContext context) {
054 this.context = context;
055 boolean enabled = context.getManagementStrategy().getStatisticsLevel() != ManagementStatisticsLevel.Off;
056 setStatisticsEnabled(enabled);
057 }
058
059 public CamelContext getContext() {
060 return context;
061 }
062
063 public String getCamelId() {
064 return context.getName();
065 }
066
067 public String getManagementName() {
068 return context.getManagementName();
069 }
070
071 public String getCamelVersion() {
072 return context.getVersion();
073 }
074
075 public String getState() {
076 return context.getStatus().name();
077 }
078
079 public String getUptime() {
080 return context.getUptime();
081 }
082
083 public Map<String, String> getProperties() {
084 if (context.getProperties().isEmpty()) {
085 return null;
086 }
087 return context.getProperties();
088 }
089
090 public Boolean getTracing() {
091 return context.isTracing();
092 }
093
094 public void setTracing(Boolean tracing) {
095 context.setTracing(tracing);
096 }
097
098 public Integer getInflightExchanges() {
099 return context.getInflightRepository().size();
100 }
101
102 public void setTimeout(long timeout) {
103 context.getShutdownStrategy().setTimeout(timeout);
104 }
105
106 public long getTimeout() {
107 return context.getShutdownStrategy().getTimeout();
108 }
109
110 public void setTimeUnit(TimeUnit timeUnit) {
111 context.getShutdownStrategy().setTimeUnit(timeUnit);
112 }
113
114 public TimeUnit getTimeUnit() {
115 return context.getShutdownStrategy().getTimeUnit();
116 }
117
118 public void setShutdownNowOnTimeout(boolean shutdownNowOnTimeout) {
119 context.getShutdownStrategy().setShutdownNowOnTimeout(shutdownNowOnTimeout);
120 }
121
122 public boolean isShutdownNowOnTimeout() {
123 return context.getShutdownStrategy().isShutdownNowOnTimeout();
124 }
125
126 public String getLoad01() {
127 return String.format("%.2f", load.getLoad1());
128 }
129
130 public String getLoad05() {
131 return String.format("%.2f", load.getLoad5());
132 }
133
134 public String getLoad15() {
135 return String.format("%.2f", load.getLoad15());
136 }
137
138 @Override
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 @Override
240 public String dumpRoutesStatsAsXml(boolean fullStats, boolean includeProcessors) throws Exception {
241 StringBuilder sb = new StringBuilder();
242 sb.append("<camelContextStat").append(String.format(" id=\"%s\"", getCamelId()));
243 // use substring as we only want the attributes
244 String stat = dumpStatsAsXml(fullStats);
245 sb.append(" ").append(stat.substring(7, stat.length() - 2)).append(">\n");
246
247 MBeanServer server = getContext().getManagementStrategy().getManagementAgent().getMBeanServer();
248 if (server != null) {
249 // gather all the routes for this CamelContext, which requires JMX
250 ObjectName query = ObjectName.getInstance("org.apache.camel:context=*/" + getContext().getManagementName() + ",type=routes,*");
251 Set<ObjectName> routes = server.queryNames(query, null);
252
253 Set<ManagedProcessorMBean> processors = new LinkedHashSet<ManagedProcessorMBean>();
254 if (includeProcessors) {
255 // gather all the processors for this CamelContext, which requires JMX
256 query = ObjectName.getInstance("org.apache.camel:context=*/" + getContext().getManagementName() + ",type=processors,*");
257 Set<ObjectName> names = server.queryNames(query, null);
258 for (ObjectName on : names) {
259 ManagedProcessorMBean processor = MBeanServerInvocationHandler.newProxyInstance(server, on, ManagedProcessorMBean.class, true);
260 processors.add(processor);
261 }
262 }
263
264 // loop the routes, and append the processor stats if needed
265 sb.append(" <routeStats>\n");
266 for (ObjectName on : routes) {
267 ManagedRouteMBean route = MBeanServerInvocationHandler.newProxyInstance(server, on, ManagedRouteMBean.class, true);
268 sb.append(" <routeStat").append(String.format(" id=\"%s\"", route.getRouteId()));
269 // use substring as we only want the attributes
270 stat = route.dumpStatsAsXml(fullStats);
271 sb.append(" ").append(stat.substring(7, stat.length() - 2)).append(">\n");
272
273 // add processor details if needed
274 if (includeProcessors) {
275 sb.append(" <processorStats>\n");
276 for (ManagedProcessorMBean processor : processors) {
277 // the processor must belong to this route
278 if (route.getRouteId().equals(processor.getRouteId())) {
279 sb.append(" <processorStat").append(String.format(" id=\"%s\"", processor.getProcessorId()));
280 // use substring as we only want the attributes
281 sb.append(" ").append(processor.dumpStatsAsXml(fullStats).substring(7)).append("\n");
282 }
283 }
284 sb.append(" </processorStats>\n");
285 }
286 sb.append(" </routeStat>\n");
287 }
288 sb.append(" </routeStats>\n");
289 }
290
291 sb.append("</camelContextStat>");
292 return sb.toString();
293 }
294
295 public boolean createEndpoint(String uri) throws Exception {
296 if (context.hasEndpoint(uri) != null) {
297 // endpoint already exists
298 return false;
299 }
300
301 Endpoint endpoint = context.getEndpoint(uri);
302 if (endpoint != null) {
303 // ensure endpoint is registered, as the management strategy could have been configured to not always
304 // register new endpoints in JMX, so we need to check if its registered, and if not register it manually
305 ObjectName on = context.getManagementStrategy().getManagementNamingStrategy().getObjectNameForEndpoint(endpoint);
306 if (on != null && !context.getManagementStrategy().getManagementAgent().isRegistered(on)) {
307 // register endpoint as mbean
308 Object me = context.getManagementStrategy().getManagementObjectStrategy().getManagedObjectForEndpoint(context, endpoint);
309 context.getManagementStrategy().getManagementAgent().register(me, on);
310 }
311 return true;
312 } else {
313 return false;
314 }
315 }
316
317 public int removeEndpoints(String pattern) throws Exception {
318 // endpoints is always removed from JMX if removed from context
319 Collection<Endpoint> removed = context.removeEndpoints(pattern);
320 return removed.size();
321 }
322
323 }