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.activemq.console.command; 018 019 020import java.util.Collection; 021import java.util.Iterator; 022import java.util.List; 023 024import javax.management.MBeanServerConnection; 025import javax.management.ObjectInstance; 026import javax.management.ObjectName; 027 028 029/** 030 * A StopGracefullyCommand 031 * 032 */ 033public 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}