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
018 package org.apache.activemq.console.command;
019
020 import java.net.URI;
021 import java.net.URISyntaxException;
022 import java.util.ArrayList;
023 import java.util.Iterator;
024 import java.util.List;
025 import java.util.concurrent.atomic.AtomicInteger;
026
027 import org.apache.activemq.broker.BrokerFactory;
028 import org.apache.activemq.broker.BrokerService;
029
030 public class StartCommand extends AbstractCommand {
031
032 public static final String DEFAULT_CONFIG_URI = "xbean:activemq.xml";
033
034 protected String[] helpFile = new String[] {
035 "Task Usage: Main start [start-options] [uri]",
036 "Description: Creates and starts a broker using a configuration file, or a broker URI.",
037 "",
038 "Start Options:",
039 " -D<name>=<value> Define a system property.",
040 " --version Display the version information.",
041 " -h,-?,--help Display the start broker help information.",
042 "",
043 "URI:",
044 "",
045 " XBean based broker configuration:",
046 "",
047 " Example: Main xbean:file:activemq.xml",
048 " Loads the xbean configuration file from the current working directory",
049 " Example: Main xbean:activemq.xml",
050 " Loads the xbean configuration file from the classpath",
051 "",
052 " URI Parameter based broker configuration:",
053 "",
054 " Example: Main broker:(tcp://localhost:61616, tcp://localhost:5000)?useJmx=true",
055 " Configures the broker with 2 transport connectors and jmx enabled",
056 " Example: Main broker:(tcp://localhost:61616, network:tcp://localhost:5000)?persistent=false",
057 " Configures the broker with 1 transport connector, and 1 network connector and persistence disabled",
058 ""
059 };
060
061 private URI configURI;
062 private List<BrokerService> brokers = new ArrayList<BrokerService>(5);
063
064 /**
065 * The default task to start a broker or a group of brokers
066 *
067 * @param brokerURIs
068 */
069 protected void runTask(List<String> brokerURIs) throws Exception {
070 try {
071 // If no config uri, use default setting
072 if (brokerURIs.isEmpty()) {
073 setConfigUri(new URI(DEFAULT_CONFIG_URI));
074 startBroker(getConfigUri());
075
076 // Set configuration data, if available, which in this case
077 // would be the config URI
078 } else {
079 String strConfigURI;
080
081 while (!brokerURIs.isEmpty()) {
082 strConfigURI = (String)brokerURIs.remove(0);
083
084 try {
085 setConfigUri(new URI(strConfigURI));
086 } catch (URISyntaxException e) {
087 context.printException(e);
088 return;
089 }
090
091 startBroker(getConfigUri());
092 }
093 }
094
095 // Prevent the main thread from exiting unless it is terminated
096 // elsewhere
097 } catch (Exception e) {
098 context.printException(new RuntimeException("Failed to execute start task. Reason: " + e, e));
099 throw new Exception(e);
100 }
101
102 // The broker start up fine. If this unblocks it's cause they were stopped
103 // and this would occur because of an internal error (like the DB going offline)
104 waitForShutdown();
105 }
106
107 /**
108 * Create and run a broker specified by the given configuration URI
109 *
110 * @param configURI
111 * @throws Exception
112 */
113 public void startBroker(URI configURI) throws Exception {
114 System.out.println("Loading message broker from: " + configURI);
115 BrokerService broker = BrokerFactory.createBroker(configURI);
116 brokers.add(broker);
117 broker.start();
118 }
119
120 /**
121 * Wait for a shutdown invocation elsewhere
122 *
123 * @throws Exception
124 */
125 protected void waitForShutdown() throws Exception {
126 final boolean[] shutdown = new boolean[] {
127 false
128 };
129
130 Runtime.getRuntime().addShutdownHook(new Thread() {
131 public void run() {
132 for (Iterator<BrokerService> i = brokers.iterator(); i.hasNext();) {
133 try {
134 BrokerService broker = i.next();
135 broker.stop();
136 } catch (Exception e) {
137 }
138 }
139 }
140 });
141
142 final AtomicInteger brokerCounter = new AtomicInteger(brokers.size());
143 for (BrokerService bs : brokers) {
144 bs.addShutdownHook(new Runnable() {
145 public void run() {
146 // When the last broker lets us know he is closed....
147 if( brokerCounter.decrementAndGet() == 0 ) {
148 synchronized (shutdown) {
149 shutdown[0] = true;
150 shutdown.notify();
151 }
152 }
153 }
154 });
155 }
156
157 // Wait for any shutdown event
158 synchronized (shutdown) {
159 while (!shutdown[0]) {
160 try {
161 shutdown.wait();
162 } catch (InterruptedException e) {
163 }
164 }
165 }
166
167 }
168
169 /**
170 * Sets the current configuration URI used by the start task
171 *
172 * @param uri
173 */
174 public void setConfigUri(URI uri) {
175 configURI = uri;
176 }
177
178 /**
179 * Gets the current configuration URI used by the start task
180 *
181 * @return current configuration URI
182 */
183 public URI getConfigUri() {
184 return configURI;
185 }
186
187 /**
188 * Print the help messages for the browse command
189 */
190 protected void printHelp() {
191 context.printHelp(helpFile);
192 }
193
194 }