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.activemq.console.command;
018    
019    import java.util.Collection;
020    import java.util.HashSet;
021    import java.util.Iterator;
022    import java.util.List;
023    
024    import javax.management.MBeanServerConnection;
025    import javax.management.ObjectInstance;
026    import javax.management.ObjectName;
027    
028    import org.apache.activemq.console.util.JmxMBeansUtil;
029    
030    public class ShutdownCommand extends AbstractJmxCommand {
031    
032        protected String[] helpFile = new String[] {
033            "Task Usage: Main stop [stop-options] [broker-name1] [broker-name2] ...",
034            "Description: Stops a running broker.",
035            "", 
036            "Stop Options:",
037            "    --jmxurl <url>             Set the JMX URL to connect to.",
038            "    --jmxuser <user>           Set the JMX user used for authenticating.",
039            "    --jmxpassword <password>   Set the JMX password used for authenticating.",
040            "    --jmxlocal                 Use the local JMX server instead of a remote one.",
041            "    --all                      Stop all brokers.",
042            "    --version                  Display the version information.",
043            "    -h,-?,--help               Display the stop broker help information.",
044            "",
045            "Broker Names:",
046            "    Name of the brokers that will be stopped.",
047            "    If omitted, it is assumed that there is only one broker running, and it will be stopped.",
048            "    Use -all to stop all running brokers.",
049            ""
050        };
051    
052        private boolean isStopAllBrokers;
053    
054        /**
055         * Shuts down the specified broker or brokers
056         * 
057         * @param brokerNames - names of brokers to shutdown
058         * @throws Exception
059         */
060        protected void runTask(List brokerNames) throws Exception {
061            try {
062                Collection mbeans;
063    
064                // Stop all brokers
065                if (isStopAllBrokers) {
066                    mbeans = JmxMBeansUtil.getAllBrokers(createJmxConnection());
067                    brokerNames.clear();
068                } else if (brokerNames.isEmpty()) {
069                    // Stop the default broker
070                    mbeans = JmxMBeansUtil.getAllBrokers(createJmxConnection());
071    
072                    // If there is no broker to stop
073                    if (mbeans.isEmpty()) {
074                        context.printInfo("There are no brokers to stop.");
075                        return;
076    
077                        // There should only be one broker to stop
078                    } else if (mbeans.size() > 1) {
079                        context.printInfo("There are multiple brokers to stop. Please select the broker(s) to stop or use --all to stop all brokers.");
080                        return;
081    
082                        // Get the first broker only
083                    } else {
084                        Object firstBroker = mbeans.iterator().next();
085                        mbeans.clear();
086                        mbeans.add(firstBroker);
087                    }
088                } else {
089                    // Stop each specified broker
090                    String brokerName;
091                    mbeans = new HashSet();
092                    while (!brokerNames.isEmpty()) {
093                        brokerName = (String)brokerNames.remove(0);
094                        Collection matchedBrokers = JmxMBeansUtil.getBrokersByName(createJmxConnection(), brokerName);
095                        if (matchedBrokers.isEmpty()) {
096                            context.printInfo(brokerName + " did not match any running brokers.");
097                        } else {
098                            mbeans.addAll(matchedBrokers);
099                        }
100                    }
101                }
102    
103                // Stop all brokers in set
104                stopBrokers(createJmxConnection(), mbeans);
105            } catch (Exception e) {
106                context.printException(new RuntimeException("Failed to execute stop task. Reason: " + e));
107                throw new Exception(e);
108            }
109        }
110    
111        /**
112         * Stops the list of brokers.
113         * 
114         * @param jmxConnection - connection to the mbean server
115         * @param brokerBeans - broker mbeans to stop @throws Exception
116         */
117        protected void stopBrokers(MBeanServerConnection jmxConnection, Collection brokerBeans) throws Exception {
118            ObjectName brokerObjName;
119            for (Iterator i = brokerBeans.iterator(); i.hasNext();) {
120                brokerObjName = ((ObjectInstance)i.next()).getObjectName();
121    
122                String brokerName = brokerObjName.getKeyProperty("BrokerName");
123                context.print("Stopping broker: " + brokerName);
124    
125                try {
126                    jmxConnection.invoke(brokerObjName, "terminateJVM", new Object[] {
127                        Integer.valueOf(0)
128                    }, new String[] {
129                        "int"
130                    });
131                    context.print("Succesfully stopped broker: " + brokerName);
132                } catch (Exception e) {
133                    // TODO: Check exceptions throwned
134                    // System.out.println("Failed to stop broker: [ " + brokerName +
135                    // " ]. Reason: " + e.getMessage());
136                }
137            }
138    
139            closeJmxConnection();
140        }
141    
142        /**
143         * Handle the --all option.
144         * 
145         * @param token - option token to handle
146         * @param tokens - succeeding command arguments
147         * @throws Exception
148         */
149        protected void handleOption(String token, List<String> tokens) throws Exception {
150            // Try to handle the options first
151            if (token.equals("--all")) {
152                isStopAllBrokers = true;
153            } else {
154                // Let the super class handle the option
155                super.handleOption(token, tokens);
156            }
157        }
158    
159        /**
160         * Print the help messages for the browse command
161         */
162        protected void printHelp() {
163            context.printHelp(helpFile);
164        }
165    
166    }