1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2000-2001,2003 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * Date Author Changes
44 * 04/07/2000 jima Created
45 */
46 package org.exolab.jms.server;
47
48 import java.sql.Connection;
49 import java.util.Enumeration;
50 import java.util.Vector;
51
52 import javax.jms.JMSException;
53 import javax.transaction.TransactionManager;
54
55 import org.apache.commons.logging.Log;
56 import org.apache.commons.logging.LogFactory;
57
58 import org.exolab.core.service.ServiceManager;
59 import org.exolab.jms.authentication.AuthenticationMgr;
60 import org.exolab.jms.authentication.User;
61 import org.exolab.jms.client.JmsDestination;
62 import org.exolab.jms.client.JmsQueue;
63 import org.exolab.jms.client.JmsTopic;
64 import org.exolab.jms.messagemgr.ConsumerEndpoint;
65 import org.exolab.jms.messagemgr.ConsumerManager;
66 import org.exolab.jms.messagemgr.DestinationCache;
67 import org.exolab.jms.messagemgr.DestinationManager;
68 import org.exolab.jms.persistence.DatabaseService;
69 import org.exolab.jms.persistence.SQLHelper;
70 import org.exolab.jms.util.UUID;
71
72
73 /***
74 * A connection is created for every adminclient connecting to the JmsServer.
75 *
76 * @version $Revision: 1.2 $ $Date: 2003/08/07 13:33:08 $
77 * @author <a href="mailto:knut@lerpold.no">Knut Lerpold</a>
78 * @see org.exolab.jms.server.AdminConnectionManager
79 */
80 public class AdminConnection {
81
82 /***
83 * This is the client that is responsible for this connection. It should
84 * map back to a client-side entity
85 */
86 private String _clientId = null;
87
88 /***
89 * The connection id is unique within the context of a JMS server
90 */
91 private String _identifierId = null;
92
93 /***
94 * The logger
95 */
96 private static final Log _log =
97 LogFactory.getLog(AdminConnection.class);
98
99 /***
100 * Instantiate an instance of this class for the specified client identity.
101 * Generates a unique identifier for this connection.
102 *
103 * @param id client identity
104 */
105 AdminConnection(String id) {
106 _clientId = id;
107 _identifierId = UUID.next();
108 }
109
110 /***
111 * Returns the client identifier
112 *
113 * @return String the client identifier
114 */
115 public String getClientId() {
116 return _clientId;
117 }
118
119 /***
120 * Returns the identifier
121 *
122 * @return String the identifierId
123 */
124 public String getIdentifierId() {
125 return _identifierId;
126 }
127
128 /***
129 * Close the admin connection
130 */
131 public void close() {
132 }
133
134 /***
135 * Determine whether the client is active
136 * Could e.g. disconnect the client if it has been inactive for a
137 * period of time.
138 *
139 * for now always return true
140 *
141 * @return boolean true if active; false otherwise
142 */
143 boolean isClientActive() {
144 boolean active = true;
145
146 return active;
147 }
148
149 /***
150 * Return the number of messages for a durable consumer.
151 *
152 * @param topic name of the topic
153 * @param name consumer name
154 * @return int number of unsent or unacked messages
155 */
156 public int getDurableConsumerMessageCount(String topic, String name) {
157 int count = -1;
158 Connection connection = null;
159
160 try {
161 // first see if the cache is loaded in memory
162 DestinationManager dmgr = DestinationManager.instance();
163 ConsumerManager cmgr = ConsumerManager.instance();
164 JmsDestination dest = dmgr.destinationFromString(topic);
165 ConsumerEndpoint endpoint = null;
166 if ((dest != null)
167 && ((name != null)
168 || (name.length() > 0))) {
169
170 endpoint = cmgr.getConsumerEndpoint(name);
171 if ((endpoint != null)
172 && (endpoint.getDestination().equals(dest))) {
173 // retrieve the number of handles for the endpoint, which
174 // reflects the number of messages
175 count = endpoint.getMessageCount();
176 } else {
177 // there is no cache with this name stored in memory. If
178 // this is an administered destination then read the count
179 // directly from the database.
180 if (dmgr.isAdministeredDestination(topic)) {
181 connection = DatabaseService.getConnection();
182 count = DatabaseService.getAdapter().
183 getDurableConsumerMessageCount(connection, topic, name);
184
185 connection.commit();
186 }
187 }
188 }
189 } catch (Exception exception) {
190 _log.error("Failed to get message count for topic=" + topic,
191 exception);
192 SQLHelper.rollback(connection);
193 } finally {
194 SQLHelper.close(connection);
195 }
196
197 return count;
198 }
199
200 /***
201 * First use the destination manager to return the number of persistent and
202 * non-persistent messages in a queue
203 *
204 * @param queue name of the queue
205 * @return int - the number of messages for that destination or -1 if the
206 * destination is invalid
207 */
208 public int getQueueMessageCount(String queue) {
209 int count = -1;
210 Connection connection = null;
211
212 try {
213 // first see if the cache is loaded in memory
214 DestinationManager mgr = DestinationManager.instance();
215 JmsDestination dest = mgr.destinationFromString(queue);
216 DestinationCache cache = null;
217 if (dest != null) {
218 cache = mgr.getDestinationCache(dest);
219
220 if (cache != null) {
221 // retrieve the number of handles for the cache, which
222 // reflects the number of messages
223 count = cache.getMessageCount();
224 } else {
225 // there is no cache with this name stored in memory. If
226 // this is an administered destination then read the count
227 // directly from the database.
228 if (mgr.isAdministeredDestination(queue)) {
229 connection = DatabaseService.getConnection();
230 count = DatabaseService.getAdapter().
231 getQueueMessageCount(connection, queue);
232 connection.commit();
233 }
234 }
235 }
236 } catch (Exception exception) {
237 _log.error("Failed to get message count for queue=" + queue,
238 exception);
239 SQLHelper.rollback(connection);
240 } finally {
241 SQLHelper.close(connection);
242 }
243
244 return count;
245 }
246
247 /***
248 * Add the specified durable consumer to the database
249 *
250 * @param topic name of the destination
251 * @param name name of the consumer
252 * @return boolean true if successful
253 */
254 public boolean addDurableConsumer(String topic, String name) {
255 boolean result = false;
256 try {
257 ConsumerManager.instance().createDurableConsumer(
258 new JmsTopic(topic), name);
259 result = true;
260 } catch (JMSException exception) {
261 _log.error("Failed to add durable consumer=" + name
262 + " for topic=" + topic, exception);
263 }
264
265 return result;
266 }
267
268 /***
269 * Remove the consumer attached to the specified destination and with
270 * the passed in name
271 *
272 * @param name name of the consumer
273 * @return boolean true if successful
274 */
275 public boolean removeDurableConsumer(String name) {
276 boolean result = false;
277 try {
278 ConsumerManager.instance().removeDurableConsumer(name);
279 result = true;
280 } catch (JMSException exception) {
281 _log.error("Failed to remove durable consumer=" + name, exception);
282 }
283
284 return result;
285 }
286
287 /***
288 * Check if the durable consumer exists.
289 *
290 * @param name name of the durable conusmer
291 * @return boolean true if it exists and false otherwise
292 */
293 public boolean durableConsumerExists(String name) {
294 return ConsumerManager.instance().durableConsumerExists(name);
295 }
296
297 /***
298 * Return the collection of durable consumer names for a particular
299 * topic destination.
300 *
301 * @param topic the topic name
302 * @return Vector collection of strings
303 */
304 public Vector getDurableConsumers(String topic) {
305 Enumeration iter = null;
306 Vector result = new Vector();
307 Connection connection = null;
308
309 try {
310 connection = DatabaseService.getConnection();
311
312 iter = DatabaseService.getAdapter().getDurableConsumers(
313 connection, topic);
314 // copy the elements into the vector
315 while (iter.hasMoreElements()) {
316 result.addElement(iter.nextElement());
317 }
318 connection.commit();
319 } catch (Exception exception) {
320 _log.error("Failed on get durable consumers for topic=" + topic,
321 exception);
322 SQLHelper.rollback(connection);
323 } finally {
324 SQLHelper.close(connection);
325 }
326
327 return result;
328 }
329
330 /***
331 * De-Activate an active persistent consumer.
332 *
333 * @param name name of the consumer
334 * @return boolean true if successful
335 */
336 public boolean unregisterConsumer(String name) {
337 boolean success = false;
338
339 try {
340 ConsumerManager.instance().deleteDurableConsumerEndpoint(name);
341 success = true;
342 } catch (JMSException exception) {
343 //
344 }
345
346 return success;
347 }
348
349 /***
350 * Check to see if the given consumer is currently connected to the
351 * OpenJMSServer. This is only valid when in online mode.
352 *
353 * @param name The name of the onsumer.
354 * @return boolean True if the consumer is connected.
355 */
356 public boolean isConnected(String name) {
357 return ConsumerManager.instance().isDurableConsumerActive(name);
358 }
359
360 /***
361 * Return a list of all registered destinations.
362 *
363 * @return Vector collection of strings
364 */
365 public Vector getAllDestinations() {
366 Enumeration iter = null;
367 Vector result = new Vector();
368 Connection connection = null;
369 TransactionManager tm = null;
370
371 try {
372 connection = DatabaseService.getConnection();
373
374 iter = DatabaseService.getAdapter().getAllDestinations(connection);
375 // copy the elements into the vector
376 while (iter.hasMoreElements()) {
377 result.addElement(iter.nextElement());
378 }
379 connection.commit();
380 } catch (Exception exception) {
381 _log.error("Failed to get all destinations", exception);
382 SQLHelper.rollback(connection);
383 } finally {
384 SQLHelper.close(connection);
385 }
386
387 return result;
388 }
389
390 /***
391 * Add an administered destination with the specified name
392 *
393 * @param name destination name
394 * @param queue whether it is queue or a topic
395 * @return boolean true if successful
396 */
397 public boolean addDestination(String name, Boolean queue) {
398
399 boolean success = false;
400
401 // create the appropriate destination object
402 JmsDestination destination = (queue.booleanValue())
403 ? (JmsDestination) new JmsQueue(name)
404 : (JmsDestination) new JmsTopic(name);
405 destination.setPersistent(true);
406
407 // create the administered destination
408 try {
409 success = DestinationManager.instance().
410 createAdministeredDestination(destination);
411 } catch (JMSException exception) {
412 _log.error("Failed to add destination=" + name, exception);
413 }
414
415 return success;
416 }
417
418 /***
419 * Destroy the specified destination and all associated messsages and
420 * consumers. This is a very dangerous operation to execute while there
421 * are clients online
422 *
423 * @param name destination to destroy
424 * @return boolean true if successful
425 */
426 public boolean removeDestination(String name) {
427
428 boolean success = false;
429 JmsDestination dest =
430 DestinationManager.instance().destinationFromString(name);
431
432 // ensure that the destination actually translates to a valid
433 // object.
434 if (dest != null) {
435 try {
436 DestinationManager.instance().deleteAdministeredDestination(dest);
437 success = true;
438 } catch (JMSException exception) {
439 _log.error("Failed to remove destination=" + name, exception);
440 }
441 }
442
443 return success;
444 }
445
446 /***
447 * Check whether the specified destination exists
448 *
449 * @param name - the name of the destination to check
450 * @return boolean - true if it does and false otherwise
451 */
452 public boolean destinationExists(String name) {
453
454 boolean exists = false;
455 DestinationManager mgr = DestinationManager.instance();
456 JmsDestination dest = mgr.destinationFromString(name);
457
458 if (dest != null) {
459 exists = mgr.destinationExists(dest);
460 }
461
462 return exists;
463 }
464
465 /***
466 * Terminate the JMS Server. If it is running as a standalone application
467 * then exit the application. It is running as an embedded application then
468 * just terminate the thread
469 */
470 public void stopServer() {
471 // todo perform neccesary clean up for a much nicer shutdown.
472 // probably should inform all clients.
473
474 _log.info("Stopping all services");
475 ServiceManager.instance().removeAll();
476 _log.info("Server Shutdown scheduled for 5 secs");
477 Runnable r = new Runnable() {
478
479 public void run() {
480 try {
481 Thread.sleep(5000);
482 System.exit(0);
483 } catch (Exception err) {
484 //
485 }
486 }
487 };
488 Thread t = new Thread(r);
489 t.start();
490 }
491
492 /***
493 * Purge all processed messages from the database
494 *
495 * @return int number of messages purged
496 */
497 public int purgeMessages() {
498 return DatabaseService.getAdapter().purgeMessages();
499 }
500
501 /***
502 * Add a user with the specified name
503 *
504 * @param username the users name
505 * @param password the users password
506 * @return <code>true</code> if the user is added
507 * otherwise <code>false</code>
508 */
509 public boolean addUser(String username, String password) {
510 return AuthenticationMgr.instance().addUser(
511 new User(username, password));
512 }
513
514 /***
515 * Change password for the specified user
516 *
517 * @param username the users name
518 * @param password the users password
519 * @return <code>true</code> if the password is changed
520 * otherwise <code>false</code>
521 */
522 public boolean changePassword(String username, String password) {
523 return AuthenticationMgr.instance().updateUser(
524 new User(username, password));
525 }
526
527 /***
528 * Remove the specified user
529 *
530 * @param username the users name
531 * @return <code>true</code> if the user is removed
532 * otherwise <code>false</code>
533 */
534 public boolean removeUser(String username) {
535 return AuthenticationMgr.instance().removeUser(
536 new User(username, null));
537 }
538
539 /***
540 * Return a list of all registered users.
541 *
542 * @return Vector of users
543 */
544 public Vector getAllUsers() {
545 Enumeration iter = null;
546 Vector result = new Vector();
547 Connection connection = null;
548
549 try {
550 connection = DatabaseService.getConnection();
551
552 iter = DatabaseService.getAdapter().getAllUsers(
553 connection);
554 // copy the elements into the vector
555 while (iter.hasMoreElements()) {
556 result.addElement(iter.nextElement());
557 }
558 connection.commit();
559 } catch (Exception exception) {
560 _log.error("Failed on get all users", exception);
561 SQLHelper.rollback(connection);
562 } finally {
563 SQLHelper.close(connection);
564 }
565
566 return result;
567 }
568
569 }
This page was automatically generated by Maven