View Javadoc

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   * $Id: IpcJmsAdminConnection.java,v 1.17 2003/08/16 09:45:46 tanderson Exp $
44   *
45   * Date         Author  Changes
46   * $Date        jimm    Created
47   */
48  package org.exolab.jms.administration.mipc;
49  
50  import java.io.IOException;
51  import java.util.Vector;
52  
53  import javax.jms.JMSException;
54  
55  import org.apache.commons.logging.Log;
56  import org.apache.commons.logging.LogFactory;
57  
58  import org.exolab.core.ipc.IpcIfc;
59  import org.exolab.core.mipc.MultiplexConnection;
60  import org.exolab.core.mipc.MultiplexConnectionIfc;
61  import org.exolab.core.mipc.ObjectChannel;
62  import org.exolab.jms.administration.AdminConnection;
63  import org.exolab.jms.administration.JmsAdminServerIfc;
64  
65  
66  /***
67   * This class is repsonsible for opening a TCP connection to the server
68   * and passing and packing all requests for delivery.
69   *
70   * @version     $Revision: 1.17 $ $Date: 2003/08/16 09:45:46 $
71   * @author      <a href="mailto:mourikis@exolab.org">Jim Mourikis</a>
72   */
73  public class IpcJmsAdminConnection implements JmsAdminServerIfc,
74      AdminConnection {
75  
76      /***
77       * This is a reference to the server connection.
78       */
79      private MultiplexConnectionIfc _mc = null;
80  
81      /***
82       * The server ipc channel
83       */
84      private IpcIfc _connection = null;
85  
86      /***
87       * The logger
88       */
89      private static final Log _log =
90          LogFactory.getLog(IpcJmsAdminConnection.class);
91  
92  
93      /***
94       * The server host address
95       */
96      private String _host;
97  
98      /***
99       * The port number the server is listening to
100      */
101     private int _port;
102 
103     /***
104      * The connection identifier, allocated by the server
105      */
106     private String _connectionId = null;
107 
108 
109     /***
110      * Construct a new <code>IpcJmsAdminConnection</code>,
111      * without establishing a connection
112      *
113      * @param host the server host
114      * @param port the server port
115      */
116     protected IpcJmsAdminConnection(String host, int port) {
117         _host = host;
118         _port = port;
119     }
120 
121     /***
122      * Construct a new <code>IpcJmsAdminConnection</code>,
123      * establishing a connection to the server
124      *
125      * @param host the server host
126      * @param port the server port
127      * @param username the admin user name
128      * @param password the admin password
129      * @throws JMSEXception if a connection cannot be established
130      */
131     public IpcJmsAdminConnection(String host, int port, String username,
132                                  String password) throws JMSException {
133         this(host, port);
134         connect(username, password);
135     }
136 
137     // implementation of JmsAdminServerIfc.addDurableConsumer
138     public boolean addDurableConsumer(String topic, String name)
139         throws JMSException {
140         Vector v = pack("addDurableConsumer", 2);
141         v.add(topic);
142         v.add(name);
143         send(v);
144         return checkReply("addDurableConsumer");
145     }
146 
147     // implementation of JmsAdminServerIfc.removeDurableConsumer
148     public boolean removeDurableConsumer(String name) throws JMSException {
149         Vector v = pack("removeDurableConsumer", 1);
150         v.add(name);
151         send(v);
152         return checkReply("removeDurableConsumer");
153     }
154 
155     // implementation of JmsAdminServerIfc.getDurableConsumers
156     public Vector getDurableConsumers(String topic) throws JMSException {
157         Vector v = pack("getDurableConsumers", 1);
158         v.add(topic);
159         send(v);
160         return (Vector) getReply("getDurableConsumers");
161     }
162 
163     // implementation of JmsAdminServerIfc.durableConsumerExists
164     public boolean durableConsumerExists(String name) throws JMSException {
165         Vector v = pack("durableConsumerExists", 1);
166         v.add(name);
167         send(v);
168         return checkReply("durableConsumerExists");
169     }
170 
171     /***
172      * Check to see if the given consumer is currently connected
173      *
174      * @param       name the name of the onsumer.
175      * @return      <code>true</code> if the consumer is connected
176      * @throws      JMSException
177      */
178     public boolean isConnected(String name) throws JMSException {
179         Vector v = pack("isConnected", 1);
180         v.add(name);
181         send(v);
182         return checkReply("isConnected");
183     }
184 
185     // implementation of JmsAdminServerIfc.removeDurableConsumer
186     public boolean unregisterConsumer(String name) throws JMSException {
187         Vector v = pack("unregisterConsumer", 1);
188         v.add(name);
189         send(v);
190         return checkReply("unregisterConsumer");
191     }
192 
193     // implementation of JmsAdminServerIfc.addDestination
194     public boolean addDestination(String destination, Boolean queue)
195         throws JMSException {
196         Vector v = pack("addDestination", 2);
197         v.add(destination);
198         v.add(queue);
199         send(v);
200         return checkReply("addDestination");
201     }
202 
203     // implementation of JmsAdminServerIfc.removeDestination
204     public boolean removeDestination(String name) throws JMSException {
205         Vector v = pack("removeDestination", 1);
206         v.add(name);
207         send(v);
208         return checkReply("removeDestination");
209     }
210 
211     // implementation of JmsAdminServerIfc.destinationExists
212     public boolean destinationExists(String name) throws JMSException {
213         Vector v = pack("destinationExists", 1);
214         v.add(name);
215         send(v);
216         return checkReply("destinationExists");
217     }
218 
219     // implementation of JmsAdminServerIfc.getAllDestinations
220     public Vector getAllDestinations() throws JMSException {
221         Vector v = pack("getAllDestinations", 0);
222         send(v);
223         return (Vector) getReply("getAllDestinations");
224     }
225 
226     // implementation of JmsAdminServerIfc.getDurableConsumerMessageCount
227     public int getDurableConsumerMessageCount(String topic, String name)
228         throws JMSException {
229         Vector v = pack("getDurableConsumerMessageCount", 2);
230         v.add(topic);
231         v.add(name);
232         send(v);
233         Integer result = (Integer) getReply("getDurableConsumerMessageCount");
234         return result.intValue();
235     }
236 
237     // implementation of JmsAdminServerIfc.getDurableConsumerMessageCount
238     public int getQueueMessageCount(String queue) throws JMSException {
239         Vector v = pack("getQueueMessageCount", 1);
240         v.add(queue);
241         send(v);
242         return ((Integer) getReply("getQueueMessageCount")).intValue();
243     }
244 
245     // implementation of JmsAdminServerIfc.purgeMessages
246     public int purgeMessages() throws JMSException {
247         Vector v = pack("purgeMessages", 0);
248         send(v);
249         return ((Integer) getReply("purgeMessages")).intValue();
250     }
251 
252     // implementation of JmsAdminServerIfc.stopServer
253     public void stopServer() throws JMSException {
254         Vector v = pack("stopServer", 0);
255         send(v);
256         checkReply("stopServer");
257     }
258 
259     // implementation of JmsAdminServerIfc.close
260     public void close() {
261         if (_connection != null) {
262             try {
263                 _connection.close();
264                 _mc.finish();
265             } catch (Exception exception) {
266                 _log.debug("Exception during close", exception);
267             }
268             _connection = null;
269             _mc = null;
270         }
271     }
272 
273     // implementation of JmsAdminServerIfc.addUser
274     public boolean addUser(String username, String password)
275         throws JMSException {
276         Vector v = pack("addUser", 2);
277         v.add(username);
278         v.add(password);
279         send(v);
280         return checkReply("addUser");
281     }
282 
283     // implementation of JmsAdminServerIfc.getAllUsers
284     public Vector getAllUsers() throws JMSException {
285         Vector v = pack("getAllUsers", 0);
286         send(v);
287         return (Vector) getReply("getAllUsers");
288     }
289 
290     // implementation of JmsAdminServerIfc.removeUser
291     public boolean removeUser(String username) throws JMSException {
292         Vector v = pack("removeUser", 1);
293         v.add(username);
294         send(v);
295         return checkReply("removeUser");
296     }
297 
298     // implementation of JmsAdminServerIfc.changePassword
299     public boolean changePassword(String username, String password)
300         throws JMSException {
301         Vector v = pack("changePassword", 2);
302         v.add(username);
303         v.add(password);
304         send(v);
305         return checkReply("changePassword");
306     }
307 
308     /***
309      * Returns the server host
310      *
311      * @return the server host
312      */
313     protected String getHost() {
314         return _host;
315     }
316 
317     /***
318      * Returns the server port
319      *
320      * @return the server port
321      */
322     protected int getPort() {
323         return _port;
324     }
325 
326     /***
327      * Returns the underlying connection
328      */
329     protected IpcIfc getConnection() {
330         return _connection;
331     }
332 
333     /***
334      * Sets the underlying connection
335      *
336      * @param connection the underlying connection
337      */
338     protected void setConnection(IpcIfc connection) {
339         _connection = connection;
340     }
341 
342     /***
343      * Opens a connection to the server.
344      *
345      * @throws JMSException if an error occurs
346      */
347     protected void openConnection() throws JMSException {
348         try {
349             _mc = createClientConnection(_host, _port);
350             _connection = new ObjectChannel("server", _mc);
351             ((Thread) _mc).start();
352         } catch (Exception exception) {
353             raise(exception);
354         }
355     }
356 
357     /***
358      * Opens an authenticated connection to the server
359      *
360      * @param username the user's name
361      * @param password the user's password
362      * @throws JMSException if the connection cannot be established
363      */
364     protected void connect(String username, String password)
365         throws JMSException {
366         openConnection();
367 
368         Vector v = pack("createConnection", 2);
369         v.add(username);
370         v.add(password);
371         send(v);
372 
373         _connectionId = (String) getReply("createConnection");
374     }
375 
376     /***
377      * Create an MIPC client connection
378      *
379      * @param host the host of the server
380      * @param port the port number to use
381      * @return a new connection
382      * @throws IOException if the server fails to initialise the ip service
383      */
384     protected MultiplexConnectionIfc createClientConnection(
385         String host, int port) throws IOException {
386         return new MultiplexConnection(host, port);
387     }
388 
389     /***
390      * Pack all the data that is required by the server in a vector.
391      * Set the size of the vector to be exactly the right size for efficiency.
392      *
393      * @param method the function to activate on the server
394      * @param num the number of additional items to pack
395      * @return a vector containing all the data
396      *
397      */
398     private Vector pack(String method, int num) {
399         Vector v = new Vector(3 + num);
400         v.add("org.exolab.jms.server.mipc.IpcJmsAdminConnection");
401         v.add(method);
402         v.add(_connectionId);
403         return v;
404     }
405 
406     /***
407      * A convenience method to send a packed command to the server.
408      * @param v the vector to be sendt
409      * @throws JMSException for any error
410      */
411     private void send(Vector v) throws JMSException {
412         try {
413             _connection.send(v);
414         } catch (Exception exception) {
415             raise(exception);
416         }
417     }
418 
419     /***
420      * A convenience method to check the success of operations which return
421      * a true on sucess.
422      *
423      * @param method the requested server function.
424      * @return true if the operation was successfull
425      * @throws JMSException for any error
426      */
427     private boolean checkReply(String method) throws JMSException {
428         boolean reply = false;
429 
430         try {
431             Vector v = (Vector) _connection.receive();
432             if (v != null) {
433                 Boolean b = (Boolean) v.get(0);
434                 if (!b.booleanValue()) {
435                     if (v.get(1) instanceof JMSException) {
436                         throw (JMSException) v.get(1);
437                     } else {
438                         throw new JMSException("Operation " + method
439                             + " failed:\n" + v.get(1));
440                     }
441                 }
442             } else {
443                 throw new JMSException("Unknown connection error for "
444                     + method);
445             }
446             reply = ((Boolean) v.get(1)).booleanValue();
447         } catch (Exception exception) {
448             raise(exception);
449         }
450         return reply;
451     }
452 
453     /***
454      * A convenience method to check the success of operations which return
455      * a value
456      *
457      * @param method the requested server function
458      * @return the data returned by the server
459      * @throws JMSException On any failure.
460      */
461     private Object getReply(String method) throws JMSException {
462         Object reply = null;
463 
464         try {
465             Vector v = (Vector) _connection.receive();
466             if (v != null) {
467                 Boolean b = (Boolean) v.get(0);
468                 if (!b.booleanValue()) {
469                     if (v.get(1) instanceof JMSException) {
470                         throw (JMSException) v.get(1);
471                     } else {
472                         throw new JMSException("Operation " + method
473                             + " failed:\n" + v.get(1));
474                     }
475                 } else {
476                     reply = v.get(1);
477                 }
478             } else {
479                 throw new JMSException("Unknown connection error for "
480                     + method);
481             }
482         } catch (Exception exception) {
483             raise(exception);
484         }
485         return reply;
486     }
487 
488     private void raise(Exception exception) throws JMSException {
489         if (exception instanceof JMSException) {
490             throw (JMSException) exception;
491         } else {
492             JMSException error = new JMSException(exception.getMessage());
493             error.setLinkedException(exception);
494             throw error;
495         }
496     }
497 
498 } //-- IpcJmsAdminConnection