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    
020    import java.util.Collection;
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    
029    /**
030     * A StopGracefullyCommand
031     *
032     */
033    public class StopGracefullyCommand extends ShutdownCommand {
034        
035            protected String connectorName, queueName;
036            protected long timeout;
037            protected long pollInterval;
038            /**
039             * Constructor
040             */
041            public StopGracefullyCommand(){
042                super();
043                this.helpFile = new String[] {
044                    "Task Usage: Main stopGracefully [stop-options] [broker-name1] [broker-name2] ...",
045                    "Description: Stops a running broker if there is no pending messages in the queues. It first stops the connector for client connection, then check queuesize until it becomes 0 before stop the broker.",
046                    "", 
047                    "Stop Options:",
048                    "    --connectorName <connectorName> connectorName to stop",
049                    "    --queueName <queueName>         check the queuesize of the queueName for pending message",
050                    "    --timeout <timeout>             periodically check the queuesize before the timeout expires",
051                    "    --pollInterval <pollInterval>   the time interval it checks the queuesize",
052                    "    --jmxurl <url>             Set the JMX URL to connect to.",
053                    "    --jmxuser <user>           Set the JMX user used for authenticating.",
054                    "    --jmxpassword <password>   Set the JMX password used for authenticating.",
055                    "    --jmxlocal                 Use the local JMX server instead of a remote one.",
056                    "    --localProcessId           Use the local process id to connect( ignore jmxurl, jmxuser, jmxpassword), need to be root to use this option",
057                    "    --all                      Stop all brokers.",
058                    "    --version                  Display the version information.",
059                    "    -h,-?,--help               Display the stop broker help information.",
060                    "",
061                    "Broker Names:",
062                    "    Name of the brokers that will be stopped.",
063                    "    If omitted, it is assumed that there is only one broker running, and it will be stopped.",
064                    "    Use -all to stop all running brokers.",
065                    ""
066                };
067            }
068    
069            /**
070             * Stops the list of brokers.
071             * 
072             * @param jmxConnection - connection to the mbean server
073             * @param brokerBeans - broker mbeans to stop @throws Exception
074             */
075            protected void stopBrokers(MBeanServerConnection jmxConnection, Collection brokerBeans) throws Exception {
076                ObjectName brokerObjName;
077                for (Iterator i = brokerBeans.iterator(); i.hasNext();) {
078                    brokerObjName = ((ObjectInstance)i.next()).getObjectName();
079    
080                    String brokerName = brokerObjName.getKeyProperty("BrokerName");
081                    context.print("Stopping broker: " + brokerName);
082    
083                    try {
084                        jmxConnection.invoke(brokerObjName, "stopGracefully", new Object[] {
085                           connectorName, queueName, timeout, pollInterval
086                        }, new String[] {
087                            "java.lang.String", "java.lang.String", "long", "long"
088                        });
089                        context.print("Succesfully stopped broker: " + brokerName);
090                    } catch (Exception e) {
091                        if(!(e.getMessage().startsWith("Error unmarshaling return header"))){
092                            context.print("Exception:"+e.getMessage());
093                        }
094                    }
095                }
096    
097                closeJmxConnection();
098            }
099        /**
100         * @param token - option token to handle
101         * @param tokens - succeeding command arguments
102         * @throws Exception
103         */
104        protected void handleOption(String token, List<String> tokens) throws Exception {
105            // Try to handle the options first
106            if (token.equals("--connectorName")) {
107                if (tokens.isEmpty() || ((String)tokens.get(0)).startsWith("-")) {
108                    context.printException(new IllegalArgumentException("connectorName not specified"));
109                    return;
110                }
111    
112                connectorName=(String)tokens.remove(0);
113            } else if (token.equals("--timeout")) {
114                if (tokens.isEmpty() || ((String)tokens.get(0)).startsWith("-")) {
115                    context.printException(new IllegalArgumentException("timeout not specified"));
116                    return;
117                }
118                timeout=Long.parseLong(tokens.remove(0));
119            } else if (token.equals("--pollInterval")) {
120                if (tokens.isEmpty() || ((String)tokens.get(0)).startsWith("-")) {
121                    context.printException(new IllegalArgumentException("pollInterval not specified"));
122                    return;
123                }
124                pollInterval=Long.parseLong(tokens.remove(0));
125            }else if(token.equals("--queueName")) {
126                if (tokens.isEmpty() || ((String)tokens.get(0)).startsWith("-")) {
127                    context.printException(new IllegalArgumentException("queueName not specified"));
128                    return;
129                }
130                queueName=(String)tokens.remove(0);
131            }else {
132                // Let the super class handle the option
133                super.handleOption(token, tokens);
134            }
135        }
136    
137    }