001 /*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements. See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership. The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied. See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 *
020 */
021 package org.apache.qpid.management.domain.services;
022
023 import java.io.BufferedReader;
024 import java.io.IOException;
025 import java.io.InputStreamReader;
026 import java.util.ArrayList;
027 import java.util.List;
028 import java.util.UUID;
029
030 import javax.management.Attribute;
031 import javax.management.AttributeList;
032 import javax.management.DynamicMBean;
033 import javax.management.MBeanException;
034 import javax.management.MBeanInfo;
035 import javax.management.MBeanOperationInfo;
036 import javax.management.MBeanParameterInfo;
037 import javax.management.Notification;
038 import javax.management.NotificationBroadcasterSupport;
039 import javax.management.NotificationListener;
040 import javax.management.ReflectionException;
041
042 import org.apache.log4j.xml.DOMConfigurator;
043 import org.apache.qpid.management.Messages;
044 import org.apache.qpid.management.Names;
045 import org.apache.qpid.management.configuration.BrokerAlreadyConnectedException;
046 import org.apache.qpid.management.configuration.BrokerConnectionData;
047 import org.apache.qpid.management.configuration.BrokerConnectionException;
048 import org.apache.qpid.management.configuration.Configurator;
049 import org.apache.qpid.management.domain.model.JmxService;
050 import org.apache.qpid.transport.util.Logger;
051
052 /**
053 * Main entry point for starting Q-Man application.
054 */
055 public class QMan extends NotificationBroadcasterSupport implements DynamicMBean, NotificationListener
056 {
057 private final static Logger LOGGER = Logger.get(QMan.class);
058 private final List<ManagementClient> managementClients = new ArrayList<ManagementClient>();
059
060 private Configurator _configurator = new Configurator();
061
062 /**
063 * Starts QMan.
064 * @throws StartupFailureException when it's not possible to proceed with startup.
065 */
066 public void start() throws StartupFailureException
067 {
068 LOGGER.info(Messages.QMAN_000001_STARTING_QMAN);
069 LOGGER.info(Messages.QMAN_000002_READING_CONFIGURATION);
070
071 try
072 {
073 registerQManService();
074
075 _configurator.configure();
076
077 LOGGER.info(Messages.QMAN_000019_QMAN_STARTED);
078 } catch(Exception exception) {
079 LOGGER.error(exception,Messages.QMAN_100018_UNABLE_TO_STARTUP_CORRECTLY );
080 throw new StartupFailureException(exception);
081 }
082 }
083
084 /**
085 * Connects Q-Man with a broker defined by the given parameter.
086 *
087 * @param host the hostname where the broker is running.
088 * @param port the port where the broker is running.
089 * @param username the username for connecting with the broker.
090 * @param password the password for connecting with the broker.
091 * @param virtualHost the virtual host.
092 * @param initialPoolCapacity the number of the connection that must be immediately opened.
093 * @param maxPoolCapacity the maximum number of opened connection.
094 * @param maxWaitTimeout the maximum amount of time that a client will wait for obtaining a connection.
095 * @throws MBeanException when it's not possible to connect with the broker.
096 */
097 public void addBroker(
098 String host,
099 int port,
100 String username,
101 String password,
102 String virtualHost,
103 int initialPoolCapacity,
104 int maxPoolCapacity,
105 long maxWaitTimeout) throws BrokerAlreadyConnectedException, BrokerConnectionException
106 {
107 Configurator configurator = new Configurator();
108 try {
109 UUID brokerId = UUID.randomUUID();
110 BrokerConnectionData data = configurator.createAndReturnBrokerConnectionData(
111 brokerId,
112 host,
113 port,
114 username,
115 password,
116 virtualHost,
117 initialPoolCapacity,
118 maxPoolCapacity,
119 maxWaitTimeout);
120 createManagementClient(brokerId, data);
121 } catch (BrokerAlreadyConnectedException exception)
122 {
123 LOGGER.warn(Messages.QMAN_300003_BROKER_ALREADY_CONNECTED, exception.getBrokerConnectionData());
124 throw exception;
125 }
126 }
127
128 /**
129 * Stop Qman
130 */
131 public void stop()
132 {
133 LOGGER.info(Messages.QMAN_000020_SHUTTING_DOWN_QMAN);
134 try
135 {
136 for (ManagementClient client : managementClients)
137 {
138 client.shutdown();
139 }
140 } catch(Exception exception)
141 {
142 }
143 LOGGER.info(Messages.QMAN_000021_SHUT_DOWN);
144 }
145
146 /**
147 * Injects the configurator on this QMan instance.
148 * That configutator later will be responsible to manage the configuration.
149 *
150 * @param configurator the configurator to be injected.
151 */
152 public void setConfigurator(Configurator configurator){
153 this._configurator = configurator;
154 }
155
156 /**
157 * Main method used for starting Q-Man.
158 *
159 * @param args the command line arguments.
160 */
161 public static void main (String[] args)
162 {
163 if (args.length == 1)
164 {
165 String logFileName = args[0];
166 DOMConfigurator.configureAndWatch(logFileName,5000);
167 }
168
169 final QMan qman = new QMan();
170
171 Thread hook = new Thread()
172 {
173 @Override
174 public void run ()
175 {
176 qman.stop();
177 }
178 };
179
180 Runtime.getRuntime().addShutdownHook(hook);
181 try
182 {
183 qman.start();
184
185 System.out.println("Type \"q\" to quit.");
186 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
187 while ( !"q".equals(reader.readLine()) )
188 {
189
190 }
191 Runtime.getRuntime().removeShutdownHook(hook);
192 qman.stop();
193 System.exit(-1);
194 } catch (StartupFailureException exception)
195 {
196 qman.stop();
197 System.exit(-1);
198 } catch (IOException exception)
199 {
200 System.exit(-1);
201 }
202 }
203
204 /**
205 * Not implemented for this MBean.
206 */
207 public Object getAttribute(String attribute)
208 {
209 return null;
210 }
211
212 /**
213 * Not implemented for this MBean.
214 */
215 public AttributeList getAttributes(String[] attributes)
216 {
217 return null;
218 }
219
220 /**
221 * Returns the metadata for this MBean
222 *
223 * @return the metadata for this MBean
224 */
225 public MBeanInfo getMBeanInfo()
226 {
227 MBeanParameterInfo parameters [] = new MBeanParameterInfo[8];
228
229 parameters[0] = new MBeanParameterInfo(
230 "host",
231 String.class.getName(),
232 "The IP address or DNS name that Qpid Broker uses to listen for incoming connections.");
233 parameters[1] = new MBeanParameterInfo(
234 "port",
235 int.class.getName(),
236 "The port number that Qpid Broker uses to listen for incoming connections.");
237 parameters[2] = new MBeanParameterInfo(
238 "username",
239 String.class.getName(),
240 "The Qpid account name used in the physical connection.");
241 parameters[3] = new MBeanParameterInfo(
242 "password",
243 String.class.getName(),
244 "The Qpid account password used in the physical connection.");
245 parameters[4]= new MBeanParameterInfo(
246 "virtualHost",
247 String.class.getName(),
248 "The virtualHost name.");
249 parameters[5]= new MBeanParameterInfo(
250 "initialPoolCapacity",
251 int.class.getName(),
252 "The number of physical connections (between 0 and a positive 32-bit integer) to create when creating the (Qpid) connection pool.");
253 parameters[6]= new MBeanParameterInfo(
254 "maxPoolCapacity",
255 int.class.getName(),
256 "The maximum number of physical database connections (between 0 and a positive 32-bit integer) that the (Qpid) connection pool can contain. ");
257 parameters[7]= new MBeanParameterInfo(
258 "maxWaitTimeout",
259 long.class.getName(),
260 "The maximum amount of time to wait for an idle connection.A value of -1 indicates an illimted amount of time (i.e. forever)");
261
262 MBeanOperationInfo operation = new MBeanOperationInfo(
263 "addBroker",
264 "Connects QMan with a broker.",
265 parameters,
266 void.class.getName(),
267 MBeanOperationInfo.ACTION);
268
269 MBeanInfo mbean = new MBeanInfo(
270 QMan.class.getName(),
271 "QMan Management & Administration interface.",
272 null,
273 null,
274 new MBeanOperationInfo[]{operation},
275 null);
276
277 return mbean;
278 }
279
280 /**
281 * Invokes an operation on QMan (MBean).
282 *
283 * @param actionName the operation name.
284 * @param params the operation parameters.
285 * @param signature the operation signature.
286 * @return the result of the invocation (if the operation is not void);
287 * @exception MBeanException Wraps a <CODE>java.lang.Exception</CODE> thrown by the MBean's invoked method.
288 * @exception ReflectionException Wraps a <CODE>java.lang.Exception</CODE> thrown while trying to invoke the method
289 */
290 public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException
291 {
292 if (Names.ADD_BROKER_OPERATION_NAME.equals(actionName))
293 {
294 try
295 {
296 addBroker(
297 (String)params[0],
298 (Integer)params[1],
299 (String)params[2],
300 (String)params[3],
301 (String)params[4],
302 (Integer)params[5],
303 (Integer)params[6],
304 (Long)params[7]);
305 } catch(Exception exception)
306 {
307 throw new MBeanException(exception);
308 }
309 } else
310 {
311 throw new ReflectionException(new NoSuchMethodException(actionName));
312 }
313 return null;
314 }
315
316 /**
317 * Not implemented for this MBean.
318 */
319 public void setAttribute(Attribute attribute)
320 {
321 }
322
323 /**
324 * Not implemented for this MBean.
325 */
326 public AttributeList setAttributes(AttributeList attributes)
327 {
328 return null;
329 }
330
331 /**
332 * Simply dispatches the incoming notification to registered listeners.
333 *
334 * @param notification the incoming notification.
335 * @param handback the context associated to this notification.
336 */
337 public void handleNotification(Notification notification, Object handback)
338 {
339 sendNotification(notification);
340 }
341
342 /**
343 * Registers QMan as an MBean on MBeanServer.
344 *
345 * @throws MBeanException when it's not possible to proceeed with registration.
346 */
347 private void registerQManService() throws MBeanException
348 {
349 JmxService service = new JmxService();
350 service.registerQManService(this);
351
352 LOGGER.info(Messages.QMAN_000023_QMAN_REGISTERED_AS_MBEAN);
353 }
354
355 /**
356 * Creates a management client using the given data.
357 *
358 * @param brokerId the broker identifier.
359 * @param data the broker connection data.
360 */
361 public void createManagementClient(UUID brokerId, BrokerConnectionData data)
362 {
363 try
364 {
365 ManagementClient client = new ManagementClient(brokerId,data);
366 client.estabilishFirstConnectionWithBroker();
367 managementClients.add(client);
368
369 LOGGER.info(Messages.QMAN_000004_MANAGEMENT_CLIENT_CONNECTED,brokerId);
370 } catch(StartupFailureException exception) {
371 LOGGER.error(exception, Messages.QMAN_100017_UNABLE_TO_CONNECT,brokerId,data);
372 }
373 }
374
375 /**
376 * Returns the list of management clients currently handled by QMan.
377 *
378 * @return the list of management clients currently handled by QMan.
379 */
380 public List<ManagementClient> getManagementClients()
381 {
382 return managementClients;
383 }
384 }
|