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 */
017package org.apache.camel.component.controlbus;
018
019import javax.management.MBeanServer;
020import javax.management.ObjectName;
021
022import org.apache.camel.AsyncCallback;
023import org.apache.camel.CamelContext;
024import org.apache.camel.Endpoint;
025import org.apache.camel.Exchange;
026import org.apache.camel.Expression;
027import org.apache.camel.Route;
028import org.apache.camel.ServiceStatus;
029import org.apache.camel.builder.ExpressionBuilder;
030import org.apache.camel.impl.DefaultAsyncProducer;
031import org.apache.camel.spi.Language;
032import org.apache.camel.util.CamelLogger;
033import org.apache.camel.util.ExchangeHelper;
034import org.apache.camel.util.ObjectHelper;
035
036/**
037 * The control bus producer.
038 */
039public class ControlBusProducer extends DefaultAsyncProducer {
040    private static final Expression ROUTE_ID_EXPRESSION = ExpressionBuilder.routeIdExpression();
041
042    private final CamelLogger logger;
043
044    public ControlBusProducer(Endpoint endpoint, CamelLogger logger) {
045        super(endpoint);
046        this.logger = logger;
047    }
048
049    @Override
050    public ControlBusEndpoint getEndpoint() {
051        return (ControlBusEndpoint) super.getEndpoint();
052    }
053
054    @Override
055    public boolean process(Exchange exchange, AsyncCallback callback) {
056        if (getEndpoint().getLanguage() != null) {
057            try {
058                processByLanguage(exchange, getEndpoint().getLanguage());
059            } catch (Exception e) {
060                exchange.setException(e);
061            }
062        } else if (getEndpoint().getAction() != null) {
063            try {
064                processByAction(exchange);
065            } catch (Exception e) {
066                exchange.setException(e);
067            }
068        }
069
070        callback.done(true);
071        return true;
072    }
073
074    protected void processByLanguage(Exchange exchange, Language language) throws Exception {
075        LanguageTask task = new LanguageTask(exchange, language);
076        if (getEndpoint().isAsync()) {
077            getEndpoint().getComponent().getExecutorService().submit(task);
078        } else {
079            task.run();
080        }
081    }
082
083    protected void processByAction(Exchange exchange) throws Exception {
084        ActionTask task = new ActionTask(exchange);
085        if (getEndpoint().isAsync()) {
086            getEndpoint().getComponent().getExecutorService().submit(task);
087        } else {
088            task.run();
089        }
090    }
091
092    /**
093     * Tasks to run when processing by language.
094     */
095    private final class LanguageTask implements Runnable {
096
097        private final Exchange exchange;
098        private final Language language;
099
100        private LanguageTask(Exchange exchange, Language language) {
101            this.exchange = exchange;
102            this.language = language;
103        }
104
105        @Override
106        public void run() {
107            String task = null;
108            Object result = null;
109
110            try {
111                // create dummy exchange
112                Exchange dummy = ExchangeHelper.createCopy(exchange, true);
113
114                task = dummy.getIn().getMandatoryBody(String.class);
115                if (task != null) {
116                    Expression exp = language.createExpression(task);
117                    result = exp.evaluate(dummy, Object.class);
118                }
119
120                if (result != null && !getEndpoint().isAsync()) {
121                    // can only set result on exchange if sync
122                    exchange.getIn().setBody(result);
123                }
124
125                if (task != null) {
126                    logger.log("ControlBus task done [" + task + "] with result -> " + (result != null ? result : "void"));
127                }
128            } catch (Exception e) {
129                logger.log("Error executing ControlBus task [" + task + "]. This exception will be ignored.", e);
130            }
131        }
132    }
133
134    /**
135     * Tasks to run when processing by route action.
136     */
137    private final class ActionTask implements Runnable {
138
139        private final Exchange exchange;
140
141        private ActionTask(Exchange exchange) {
142            this.exchange = exchange;
143        }
144
145        @Override
146        public void run() {
147            String action = getEndpoint().getAction();
148            String id = getEndpoint().getRouteId();
149
150            if (ObjectHelper.equal("current", id)) {
151                id = ROUTE_ID_EXPRESSION.evaluate(exchange, String.class);
152            }
153
154            Object result = null;
155            String task = action + " route " + id;
156
157            try {
158                if ("start".equals(action)) {
159                    getEndpoint().getCamelContext().startRoute(id);
160                } else if ("stop".equals(action)) {
161                    getEndpoint().getCamelContext().stopRoute(id);
162                } else if ("suspend".equals(action)) {
163                    getEndpoint().getCamelContext().suspendRoute(id);
164                } else if ("resume".equals(action)) {
165                    getEndpoint().getCamelContext().resumeRoute(id);
166                } else if ("status".equals(action)) {
167                    ServiceStatus status = getEndpoint().getCamelContext().getRouteStatus(id);
168                    if (status != null) {
169                        result = status.name();
170                    }
171                } else if ("stats".equals(action)) {
172
173                    // camel context or per route
174                    String name = getEndpoint().getCamelContext().getManagementName();
175                    if (name == null) {
176                        result = "JMX is disabled, cannot get stats";
177                    } else {
178                        ObjectName on;
179                        String operation;
180                        if (id == null) {
181                            CamelContext camelContext = getEndpoint().getCamelContext();
182                            on = getEndpoint().getCamelContext().getManagementStrategy().getManagementNamingStrategy().getObjectNameForCamelContext(camelContext);
183                            operation = "dumpRoutesStatsAsXml";
184                        } else {
185                            Route route = getEndpoint().getCamelContext().getRoute(id);
186                            on = getEndpoint().getCamelContext().getManagementStrategy().getManagementNamingStrategy().getObjectNameForRoute(route);
187                            operation = "dumpRouteStatsAsXml";
188                        }
189                        if (on != null) {
190                            MBeanServer server = getEndpoint().getCamelContext().getManagementStrategy().getManagementAgent().getMBeanServer();
191                            result = server.invoke(on, operation, new Object[]{true, true}, new String[]{"boolean", "boolean"});
192                        } else {
193                            result = "Cannot lookup route with id " + id;
194                        }
195                    }
196                }
197
198                if (result != null && !getEndpoint().isAsync()) {
199                    // can only set result on exchange if sync
200                    exchange.getIn().setBody(result);
201                }
202
203                logger.log("ControlBus task done [" + task + "] with result -> " + (result != null ? result : "void"));
204            } catch (Exception e) {
205                logger.log("Error executing ControlBus task [" + task + "]. This exception will be ignored.", e);
206            }
207        }
208    }
209
210}