KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > mq > sm > AbstractStateManager


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.mq.sm;
23
24 import java.util.Collection JavaDoc;
25 import java.util.HashSet JavaDoc;
26 import java.util.Set JavaDoc;
27
28 import javax.jms.InvalidClientIDException JavaDoc;
29 import javax.jms.InvalidDestinationException JavaDoc;
30 import javax.jms.JMSException JavaDoc;
31 import javax.jms.JMSSecurityException JavaDoc;
32
33 import org.jboss.mq.DurableSubscriptionID;
34 import org.jboss.mq.SpyTopic;
35 import org.jboss.mq.server.JMSDestinationManager;
36 import org.jboss.mq.server.JMSTopic;
37 import org.jboss.system.ServiceMBeanSupport;
38 import org.jboss.util.JBossStringBuilder;
39
40 /**
41  * An abstract baseclass to make it a little bit easier to implement new
42  * StateManagers.
43  *
44  * <p>Apart from one methods in StateManager subclasses implement the
45  * protected abstract callback methods to do its work.
46  *
47  * @author <a HREF="pra@tim.se">Peter Antman </a>
48  * @author <a HREF="Norbert.Lataille@m4x.org">Norbert Lataille </a>
49  * @author <a HREF="hiram.chirino@jboss.org">Hiram Chirino </a>
50  * @author <a HREF="adrian@jboss.com">Adrian Brock </a>
51  * @version $Revision: 38284 $
52  */

53
54 public abstract class AbstractStateManager extends ServiceMBeanSupport
55    implements StateManager, AbstractStateManagerMBean
56 {
57    /** The logged on client ids */
58    private final Set JavaDoc loggedOnClientIds = new HashSet JavaDoc();
59
60    /**
61     * Create a new abstract state manager
62     */

63    public AbstractStateManager()
64    {
65    }
66
67    public void setDurableSubscription(JMSDestinationManager server, DurableSubscriptionID sub, SpyTopic topic)
68          throws JMSException JavaDoc
69    {
70       boolean debug = log.isDebugEnabled();
71       if (debug)
72          log.debug("Checking durable subscription: " + sub + ", on topic: " + topic);
73
74       DurableSubscription subscription = getDurableSubscription(sub);
75
76       // A new subscription
77
if (subscription == null)
78       {
79          if (debug)
80             log.debug("The subscription was not previously registered " + sub);
81          // Either this was a remove attemt, not to successfull,
82
// or it was a bogus request (should then an exception be raised?)
83
if (topic == null)
84             return;
85          // Create the real durable subscription
86
JMSTopic dest = (JMSTopic) server.getJMSDestination(topic);
87          if (dest == null)
88             throw new InvalidDestinationException JavaDoc("Topic does not exist: " + topic);
89          dest.createDurableSubscription(sub);
90
91          // Save it
92
subscription = new DurableSubscription(sub.getClientID(), sub.getSubscriptionName(), topic.getName(), sub
93                .getSelector());
94          // Call subclass
95
saveDurableSubscription(subscription);
96       }
97       // An existing subscription...it was previously registered...
98
// Check if it is an unsubscribe, or a change of subscription.
99
else
100       {
101          if (debug)
102             log.debug("The subscription was previously registered: " + subscription);
103
104          String JavaDoc newSelector = sub.getSelector();
105          String JavaDoc oldSelector = subscription.getSelector();
106          boolean selectorChanged = false;
107          if ((newSelector == null && oldSelector != null)
108                || (newSelector != null && newSelector.equals(oldSelector) == false))
109             selectorChanged = true;
110
111          // The client wants an unsubscribe
112
// TODO: we are not spec compliant since we neither check if
113
// the topic has an active subscriber or if there are messages
114
// destined for the client not yet acked by the session!!!
115
if (topic == null)
116          {
117             if (debug)
118                log.debug("Removing subscription: " + subscription);
119             // we have to change the subscription...do physical work
120
SpyTopic prevTopic = new SpyTopic(subscription.getTopic());
121             JMSTopic dest = (JMSTopic) server.getJMSDestination(prevTopic);
122             if (dest == null)
123                throw new InvalidDestinationException JavaDoc("Topic does not exist: " + prevTopic);
124             // TODO here we should check if the client still has
125
// an active consumer
126

127             dest.destroyDurableSubscription(sub);
128
129             //straight deletion, remove subscription - call subclass
130
removeDurableSubscription(subscription);
131          }
132          // The topic previously subscribed to is not the same as the
133
// one in the subscription request.
134
else if (!subscription.getTopic().equals(topic.getName()) || selectorChanged)
135          {
136             //new topic so we have to change it
137
if (debug)
138                log.debug("But the topic or selector was different, changing the subscription.");
139             // remove the old sub
140
SpyTopic prevTopic = new SpyTopic(subscription.getTopic());
141             JMSTopic dest = (JMSTopic) server.getJMSDestination(prevTopic);
142             if (dest == null)
143                throw new InvalidDestinationException JavaDoc("Previous topic does not exist: " + prevTopic);
144             dest.destroyDurableSubscription(sub);
145
146             // Create the new
147
dest = (JMSTopic) server.getJMSDestination(topic);
148             if (dest == null)
149                throw new InvalidDestinationException JavaDoc("Topic does not exist: " + topic);
150             dest.createDurableSubscription(sub);
151
152             //durable subscription has new topic, save.
153
subscription.setTopic(topic.getName());
154             subscription.setSelector(sub.getSelector());
155             saveDurableSubscription(subscription);
156          }
157       }
158    }
159
160    public SpyTopic getDurableTopic(DurableSubscriptionID sub) throws JMSException JavaDoc
161    {
162       DurableSubscription subscription = getDurableSubscription(sub);
163       if (subscription == null)
164          throw new InvalidDestinationException JavaDoc("No durable subscription found for subscription: "
165                + sub.getSubscriptionName());
166
167       return new SpyTopic(subscription.getTopic());
168    }
169
170    public String JavaDoc checkUser(String JavaDoc login, String JavaDoc passwd) throws JMSException JavaDoc
171    {
172       String JavaDoc clientId = getPreconfClientId(login, passwd);
173       
174       if (clientId != null)
175       {
176          synchronized (loggedOnClientIds)
177          {
178             if (loggedOnClientIds.contains(clientId))
179             {
180                throw new JMSSecurityException JavaDoc
181                   ("The login id has an assigned client id '" + clientId +
182                    "', that is already connected to the server!");
183             }
184             loggedOnClientIds.add(clientId);
185          }
186       }
187
188       return clientId;
189    }
190
191    public void addLoggedOnClientId(String JavaDoc ID) throws JMSException JavaDoc
192    {
193       synchronized (loggedOnClientIds)
194       {
195          if (loggedOnClientIds.contains(ID))
196             throw new InvalidClientIDException JavaDoc("This client id '" + ID + "' is already registered!");
197       }
198       
199       checkLoggedOnClientId(ID);
200
201       synchronized (loggedOnClientIds)
202       {
203          loggedOnClientIds.add(ID);
204       }
205       if (log.isTraceEnabled())
206          log.trace("Client id '" + ID + "' is logged in.");
207    }
208
209    public void removeLoggedOnClientId(String JavaDoc ID)
210    {
211       synchronized (loggedOnClientIds)
212       {
213          loggedOnClientIds.remove(ID);
214       }
215       if (log.isTraceEnabled())
216          log.trace("Client id '" + ID + "' is logged out.");
217    }
218
219    abstract public Collection JavaDoc getDurableSubscriptionIdsForTopic(SpyTopic topic) throws JMSException JavaDoc;
220
221    /**
222     * Get preconfigured clientID for login/user, and if state manager wants
223     * do authentication. This is NOT recomended when using a SecurityManager.
224     *
225     * @param login the user name
226     * @param passwd the password
227     * @return any preconfigured client id
228     * @throws JMSException for any error
229     */

230    abstract protected String JavaDoc getPreconfClientId(String JavaDoc login, String JavaDoc passwd) throws JMSException JavaDoc;
231
232    /**
233     * Check if the clientID is allowed to logg in from the particular state
234     * managers perspective.
235     *
236     * @param clientID the client id to check
237     * @throws JMSException for any error
238     */

239    abstract protected void checkLoggedOnClientId(String JavaDoc clientID) throws JMSException JavaDoc;
240
241    /**
242     * Get a DurableSubscription.
243     *
244     * @param sub the durable subscription id
245     * @return the durable subscription or null if not found
246     * @throws JMSException for any error
247     */

248    abstract protected DurableSubscription getDurableSubscription(DurableSubscriptionID sub) throws JMSException JavaDoc;
249
250    /**
251     * Add to durable subs and save the subsrcription to persistent storage.<p>
252     *
253     * Called by this class so the sublclass can save. This may be both
254     * a new subscription or a changed one. It is up to the sublcass
255     * to know how to find a changed on. (Only the topic will have changed,
256     * and it is the same DurableSubscription that is saved again that this
257     * class got through getDurableSubscription.
258     *
259     * @param ds the durable subscription to save
260     * @throws JMSException for any error
261     */

262    abstract protected void saveDurableSubscription(DurableSubscription ds) throws JMSException JavaDoc;
263
264    /**
265     * Remove the subscription and save to persistent storage.<p>
266     *
267     * Called by this class so the sublclass can remove.
268     *
269     * @param ds the durable subscription to save
270     * @throws JMSException for any error
271     */

272    abstract protected void removeDurableSubscription(DurableSubscription ds) throws JMSException JavaDoc;
273
274    /**
275     * Abstracts the data between a subclass and this class.
276     *
277     * A sublcass can extends this class to ad custom behaviour.
278     */

279    protected class DurableSubscription
280    {
281       /** The client id of the durable subscription */
282       String JavaDoc clientID;
283
284       /** The subscription name of the durable subscription */
285       String JavaDoc name;
286
287       /** The topic name of the durable subscription */
288       String JavaDoc topic;
289
290       /** Any message selector of the durable subscription */
291       String JavaDoc selector;
292
293       /**
294        * Create a new DurableSubscription.
295        */

296       public DurableSubscription()
297       {
298       }
299
300       /**
301        * Create a new DurableSubscription.
302        *
303        * @param clientID the client id
304        * @param name the subscription name
305        * @param topic the topic name
306        * @param selector any message selector
307        */

308       public DurableSubscription(String JavaDoc clientID, String JavaDoc name, String JavaDoc topic, String JavaDoc selector)
309       {
310          this.clientID = clientID;
311          this.name = name;
312          this.topic = topic;
313          this.selector = selector;
314       }
315       
316       /**
317        * Get the client id
318        *
319        * @return the client id
320        */

321       public String JavaDoc getClientID()
322       {
323          return clientID;
324       }
325
326       /**
327        * Get the subcription name
328        *
329        * @return the subscription name
330        */

331       public String JavaDoc getName()
332       {
333          return name;
334       }
335
336       /**
337        * Get the topic name
338        *
339        * @return the topic name
340        */

341       public String JavaDoc getTopic()
342       {
343          return topic;
344       }
345
346       /**
347        * Set the topic name
348        *
349        * @param topic the internal name of the topic
350        */

351       public void setTopic(String JavaDoc topic)
352       {
353          this.topic = topic;
354       }
355
356       /**
357        * Gets the selector.
358        *
359        * @return the selector
360        */

361       public String JavaDoc getSelector()
362       {
363          return selector;
364       }
365
366       /**
367        * Sets the selector.
368        *
369        * @param selector The selector to set
370        */

371       public void setSelector(String JavaDoc selector)
372       {
373          this.selector = selector;
374       }
375
376       public String JavaDoc toString()
377       {
378          JBossStringBuilder buffer = new JBossStringBuilder();
379          buffer.append("DurableSub[clientID=").append(clientID);
380          buffer.append(" name=").append(name);
381          buffer.append(" topic=").append(topic);
382          buffer.append(" selector=").append(selector);
383          buffer.append(']');
384          return buffer.toString();
385       }
386    }
387 }
Popular Tags