001/* 002 * (C) Copyright 2006-2017 Nuxeo (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nuxeo - initial API and implementation 018 * Kevin Leturc <kleturc@nuxeo.com> 019 */ 020package org.nuxeo.runtime.services.event; 021 022import java.util.HashMap; 023import java.util.Hashtable; 024import java.util.Map; 025 026import org.apache.commons.lang3.ArrayUtils; 027import org.apache.commons.logging.Log; 028import org.apache.commons.logging.LogFactory; 029import org.nuxeo.common.collections.ListenerList; 030import org.nuxeo.runtime.model.ComponentContext; 031import org.nuxeo.runtime.model.ComponentName; 032import org.nuxeo.runtime.model.DefaultComponent; 033import org.nuxeo.runtime.model.Extension; 034 035/** 036 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 037 */ 038public class EventService extends DefaultComponent { 039 040 public static final ComponentName NAME = new ComponentName("org.nuxeo.runtime.EventService"); 041 042 private static final Log log = LogFactory.getLog(EventService.class); 043 044 private final Map<String, ListenerList> topics; 045 046 private final Map<String, Object[]> contributions; 047 048 public EventService() { 049 topics = new HashMap<>(); 050 contributions = new Hashtable<>(); 051 } 052 053 @Override 054 public void deactivate(ComponentContext context) { 055 topics.clear(); 056 contributions.clear(); 057 } 058 059 @Override 060 public void registerExtension(Extension extension) { 061 Object[] descriptors = extension.getContributions(); 062 if (ArrayUtils.isEmpty(descriptors)) { 063 return; 064 } 065 String name = extension.getId(); 066 synchronized (this) { 067 for (Object desc : descriptors) { 068 ListenerDescriptor lDesc = (ListenerDescriptor) desc; 069 for (String topic : lDesc.topics) { 070 addListener(topic, lDesc.listener); 071 } 072 } 073 contributions.put(name, descriptors); 074 } 075 } 076 077 @Override 078 public void unregisterExtension(Extension extension) { 079 String name = extension.getId(); 080 synchronized (this) { 081 Object[] descriptors = contributions.remove(name); 082 if (descriptors != null) { 083 for (Object desc : descriptors) { 084 ListenerDescriptor lDesc = (ListenerDescriptor) desc; 085 for (String topic : lDesc.topics) { 086 removeListener(topic, lDesc.listener); 087 } 088 } 089 } 090 } 091 } 092 093 public void sendEvent(Event event) { 094 ListenerList list = topics.get(event.getTopic()); 095 if (list == null) { 096 if (log.isTraceEnabled()) { 097 log.trace("Event sent to topic " + event.getTopic() + ". Ingnoring"); 098 } 099 } else { 100 sendEvent(list, event); 101 } 102 } 103 104 public synchronized void addListener(String topic, EventListener listener) { 105 ListenerList list = topics.get(topic); 106 if (list == null) { 107 list = new ListenerList(); 108 topics.put(topic, list); 109 } 110 list.add(listener); 111 } 112 113 public synchronized void removeListener(String topic, EventListener listener) { 114 ListenerList list = topics.get(topic); 115 if (list != null) { 116 list.remove(listener); 117 if (list.isEmpty()) { 118 topics.remove(topic); 119 } 120 } 121 } 122 123 private static void sendEvent(ListenerList list, Event event) { 124 Object[] listeners = list.getListeners(); 125 for (Object listener : listeners) { 126 ((EventListener) listener).handleEvent(event); 127 } 128 } 129 130 @Override 131 @SuppressWarnings("unchecked") 132 public <T> T getAdapter(Class<T> adapter) { 133 return adapter == getClass() ? (T) this : null; 134 } 135 136}