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