}
public void addSubscriber(Object clientId, String selector, String subtopicString, String endpointId)
{
Subtopic subtopic = getSubtopic(subtopicString);
MessageClient client = null;
TopicSubscription topicSub;
Map subs;
Map map;
try
{
// Handle resubscribes from the same client and duplicate subscribes from different clients
boolean subscriptionAlreadyExists = (getSubscriber(clientId) != null);
client = getMessageClient(clientId, endpointId);
FlexClient flexClient = FlexContext.getFlexClient();
if (subscriptionAlreadyExists)
{
// Block duplicate subscriptions from multiple FlexClients if they
// attempt to use the same clientId. (when this is called from a remote
// subscription, there won't be a flex client so skip this test).
if (flexClient != null && !flexClient.getId().equals(client.getFlexClient().getId()))
{
ServiceException se = new ServiceException();
se.setMessage(10559, new Object[] {clientId});
throw se;
}
// It's a resubscribe. Reset the endpoint push state for the subscription to make sure its current
// because a resubscribe could be arriving over a new endpoint or a new session.
client.resetEndpoint(endpointId);
}
ServiceAdapter adapter = destination.getAdapter();
client.updateLastUse();
if (subtopic == null)
{
topicSub = globalSubscribers;
}
else
{
if (!destination.getServerSettings().getAllowSubtopics())
{
// Throw an error - the destination doesn't allow subtopics.
ServiceException se = new ServiceException();
se.setMessage(SUBTOPICS_NOT_SUPPORTED, new Object[] {subtopicString, destination.getId()});
throw se;
}
// Give a MessagingAdapter a chance to block the subscribe.
if ((adapter instanceof MessagingSecurity) && (subtopic != null))
{
if (!((MessagingSecurity)adapter).allowSubscribe(subtopic))
{
ServiceException se = new ServiceException();
se.setMessage(10557, new Object[] {subtopicString});
throw se;
}
}
/*
* If there is a wildcard, we always need to match that subscription
* against the producer. If it has no wildcard, we can do a quick
* lookup to find the subscribers.
*/
if (subtopic.containsSubtopicWildcard())
map = subscribersPerSubtopicWildcard;
else
map = subscribersPerSubtopic;
topicSub = (TopicSubscription) map.get(subtopic);
if (topicSub == null)
{
synchronized (this)
{
topicSub = (TopicSubscription) map.get(subtopic);
if (topicSub == null)
{
topicSub = new TopicSubscription();
map.put(subtopic, topicSub);
}
}
}
}
/* Subscribing with no selector */
if (selector == null)
{
subs = topicSub.defaultSubscriptions;
if (subs == null)
{
synchronized (this)
{
if ((subs = topicSub.defaultSubscriptions) == null)
topicSub.defaultSubscriptions = subs = new ConcurrentHashMap();
}
}
}
/* Subscribing with a selector - store all subscriptions under the selector key */
else
{
if (topicSub.selectorSubscriptions == null)
{
synchronized (this)
{
if (topicSub.selectorSubscriptions == null)
topicSub.selectorSubscriptions = new ConcurrentHashMap();
}
}
subs = (Map) topicSub.selectorSubscriptions.get(selector);
if (subs == null)
{
synchronized (this)
{
if ((subs = (Map) topicSub.selectorSubscriptions.get(selector)) == null)
topicSub.selectorSubscriptions.put(selector, subs = new ConcurrentHashMap());
}
}
}
if (subs.containsKey(clientId))
{
/* I'd rather this be an error but in 2.0 we allowed this without error */
if (Log.isWarn())
Log.getLogger(JMSSelector.LOG_CATEGORY).warn("Client: " + clientId + " already subscribed to: " + destination.getId() + " selector: " + selector + " subtopic: " + subtopicString);
}
else
{
client.addSubscription(selector, subtopicString);
synchronized (this)
{
/*
* Make sure other members of the cluster know that we are subscribed to
* this info if we are in server-to-server mode