// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. Citrix Systems, Inc.
// reserves all rights not expressly granted by the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.utils.events;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
public class SubscriptionMgr {
protected final static Logger s_logger = Logger.getLogger(SubscriptionMgr.class);
private static SubscriptionMgr s_instance = new SubscriptionMgr();
private Map<String, List<SubscriberInfo>> registry;
private SubscriptionMgr() {
registry = new HashMap<String, List<SubscriberInfo>>();
}
public static SubscriptionMgr getInstance() {
return s_instance;
}
public <T> void subscribe(String subject, T subscriber, String listenerMethod)
throws SecurityException, NoSuchMethodException {
synchronized(this) {
List<SubscriberInfo> l = getAndSetSubscriberList(subject);
Class<?> clazz = subscriber.getClass();
SubscriberInfo subscribeInfo = new SubscriberInfo(clazz, subscriber, listenerMethod);
if(!l.contains(subscribeInfo))
l.add(subscribeInfo);
}
}
public <T> void unsubscribe(String subject, T subscriber, String listenerMethod) {
synchronized(this) {
List<SubscriberInfo> l = getSubscriberList(subject);
if(l != null) {
for(SubscriberInfo info : l) {
if(info.isMe(subscriber.getClass(), subscriber, listenerMethod)) {
l.remove(info);
return;
}
}
}
}
}
public void notifySubscribers(String subject, Object sender, EventArgs args) {
List<SubscriberInfo> l = getExecutableSubscriberList(subject);
if(l != null) {
for(SubscriberInfo info : l) {
try {
info.execute(sender, args);
} catch (IllegalArgumentException e) {
s_logger.warn("Exception on notifying event subscribers: ", e);
} catch (IllegalAccessException e) {
s_logger.warn("Exception on notifying event subscribers: ", e);
} catch (InvocationTargetException e) {
s_logger.warn("Exception on notifying event subscribers: ", e);
}
}
}
}
private List<SubscriberInfo> getAndSetSubscriberList(String subject) {
List<SubscriberInfo> l = registry.get(subject);
if(l == null) {
l = new ArrayList<SubscriberInfo>();
registry.put(subject, l);
}
return l;
}
private List<SubscriberInfo> getSubscriberList(String subject) {
return registry.get(subject);
}
private synchronized List<SubscriberInfo> getExecutableSubscriberList(String subject) {
List<SubscriberInfo> l = registry.get(subject);
if(l != null) {
// do a shadow clone
ArrayList<SubscriberInfo> clonedList = new ArrayList<SubscriberInfo>(l.size());
for(SubscriberInfo info : l)
clonedList.add(info);
return clonedList;
}
return null;
}
private static class SubscriberInfo {
private Class<?> clazz;
private Object subscriber;
private String methodName;
private Method method;
public SubscriberInfo(Class<?> clazz, Object subscriber, String methodName)
throws SecurityException, NoSuchMethodException {
this.clazz = clazz;
this.subscriber = subscriber;
this.methodName = methodName;
for(Method method : clazz.getMethods()) {
if(method.getName().equals(methodName)) {
Class<?>[] paramTypes = method.getParameterTypes();
if(paramTypes != null && paramTypes.length == 2 &&
paramTypes[0] == Object.class &&
EventArgs.class.isAssignableFrom(paramTypes[1])) {
this.method = method;
break;
}
}
}
if(this.method == null)
throw new NoSuchMethodException();
}
public void execute(Object sender, EventArgs args)
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
method.invoke(subscriber, sender, args);
}
public boolean isMe(Class<?> clazz, Object subscriber, String methodName) {
return this.clazz == clazz &&
this.subscriber == subscriber &&
this.methodName.equals(methodName);
}
public boolean equals(Object o) {
if(o == null)
return false;
if(o instanceof SubscriberInfo) {
return this.clazz == ((SubscriberInfo)o).clazz &&
this.subscriber == ((SubscriberInfo)o).subscriber &&
this.methodName.equals(((SubscriberInfo)o).methodName);
}
return false;
}
}
}