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