tmf: Switch tmf.core to Java 7 + fix warnings
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / signal / TmfSignalManager.java
CommitLineData
8c8bf09f 1/*******************************************************************************
11252342 2 * Copyright (c) 2009, 2013 Ericsson
6256d8ad 3 *
8c8bf09f
ASL
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
6256d8ad 8 *
8c8bf09f
ASL
9 * Contributors:
10 * Francois Chouinard - Initial API and implementation
fec1ac0b 11 * Bernd Hufmann - Update register methods
8c8bf09f
ASL
12 *******************************************************************************/
13
6c13869b 14package org.eclipse.linuxtools.tmf.core.signal;
8c8bf09f
ASL
15
16import java.lang.reflect.InvocationTargetException;
17import java.lang.reflect.Method;
18import java.util.ArrayList;
19import java.util.HashMap;
20import java.util.List;
21import java.util.Map;
22
8555a0f3 23import org.eclipse.linuxtools.internal.tmf.core.Activator;
5500a7f0 24import org.eclipse.linuxtools.internal.tmf.core.TmfCoreTracer;
dc299841 25
8c8bf09f 26/**
8d2e2848
FC
27 * This class manages the set of signal listeners and the signals they are
28 * interested in. When a signal is broadcasted, the appropriate listeners
29 * signal handlers are invoked.
6256d8ad 30 *
4b7b3670
FC
31 * @version 1.0
32 * @author Francois Chouinard
4f8ca6a1 33 */
8c8bf09f
ASL
34public class TmfSignalManager {
35
d9ec9800
AM
36 // The set of event listeners and their corresponding handler methods.
37 // Note: listeners could be restricted to ITmfComponents but there is no
38 // harm in letting anyone use this since it is not tied to anything but
39 // the signal data type.
a4524c1b
AM
40 private static Map<Object, Method[]> fListeners = new HashMap<>();
41 private static Map<Object, Method[]> fVIPListeners = new HashMap<>();
d9ec9800
AM
42
43 // If requested, add universal signal tracer
44 // TODO: Temporary solution: should be enabled/disabled dynamically
45 private static boolean fTraceIsActive = false;
46 private static TmfSignalTracer fSignalTracer;
47
48 static {
49 if (fTraceIsActive) {
50 fSignalTracer = TmfSignalTracer.getInstance();
51 register(fSignalTracer);
52 }
53 }
8c8bf09f 54
4f8ca6a1
AM
55 /**
56 * Register an object to the signal manager. This object can then implement
57 * handler methods, marked with @TmfSignalHandler and with the expected
58 * signal type as parameter.
59 *
60 * @param listener
61 * The object that will be notified of new signals
62 */
63 public static synchronized void register(Object listener) {
fec1ac0b 64 deregister(listener); // make sure that listener is only registered once
4f8ca6a1
AM
65 Method[] methods = getSignalHandlerMethods(listener);
66 if (methods.length > 0) {
67 fListeners.put(listener, methods);
68 }
69 }
8c8bf09f 70
4f8ca6a1
AM
71 /**
72 * Register an object to the signal manager as a "VIP" listener. All VIP
73 * listeners will all receive the signal before the manager moves on to the
74 * lowly, non-VIP listeners.
75 *
76 * @param listener
77 * The object that will be notified of new signals
78 */
d5c13688 79 public static synchronized void registerVIP(Object listener) {
fec1ac0b 80 deregister(listener); // make sure that listener is only registered once
d5c13688 81 Method[] methods = getSignalHandlerMethods(listener);
6256d8ad 82 if (methods.length > 0) {
d5c13688 83 fVIPListeners.put(listener, methods);
6256d8ad 84 }
d5c13688
FC
85 }
86
4f8ca6a1
AM
87 /**
88 * De-register a listener object from the signal manager. This means that
89 * its @TmfSignalHandler methods will no longer be called.
90 *
91 * @param listener
92 * The object to de-register
93 */
94 public static synchronized void deregister(Object listener) {
95 fVIPListeners.remove(listener);
d5c13688 96 fListeners.remove(listener);
4f8ca6a1 97 }
8c8bf09f 98
d9ec9800
AM
99 /**
100 * Returns the list of signal handlers in the listener. Signal handler name
101 * is irrelevant; only the annotation (@TmfSignalHandler) is important.
102 *
103 * @param listener
104 * @return
105 */
106 private static Method[] getSignalHandlerMethods(Object listener) {
a4524c1b 107 List<Method> handlers = new ArrayList<>();
d9ec9800
AM
108 Method[] methods = listener.getClass().getMethods();
109 for (Method method : methods) {
110 if (method.isAnnotationPresent(TmfSignalHandler.class)) {
111 handlers.add(method);
112 }
113 }
114 return handlers.toArray(new Method[handlers.size()]);
115 }
116
117 static int fSignalId = 0;
118
119 /**
120 * Invokes the handling methods that listens to signals of a given type.
121 *
122 * The list of handlers is built on-the-fly to allow for the dynamic
123 * creation/deletion of signal handlers. Since the number of signal handlers
124 * shouldn't be too high, this is not a big performance issue to pay for the
125 * flexibility.
126 *
127 * For synchronization purposes, the signal is bracketed by two synch
128 * signals.
129 *
130 * @param signal
131 * the signal to dispatch
132 */
133 public static synchronized void dispatchSignal(TmfSignal signal) {
134 int signalId = fSignalId++;
135 sendSignal(new TmfStartSynchSignal(signalId));
136 signal.setReference(signalId);
137 sendSignal(signal);
138 sendSignal(new TmfEndSynchSignal(signalId));
139 }
140
141 private static void sendSignal(TmfSignal signal) {
d5c13688
FC
142 sendSignal(fVIPListeners, signal);
143 sendSignal(fListeners, signal);
144 }
145
d9ec9800 146 private static void sendSignal(Map<Object, Method[]> listeners, TmfSignal signal) {
d5c13688 147
5500a7f0
FC
148 if (TmfCoreTracer.isSignalTraced()) {
149 TmfCoreTracer.traceSignal(signal, "(start)"); //$NON-NLS-1$
6256d8ad 150 }
d5c13688
FC
151
152 // Build the list of listener methods that are registered for this signal
153 Class<?> signalClass = signal.getClass();
a4524c1b 154 Map<Object, List<Method>> targets = new HashMap<>();
d5c13688
FC
155 targets.clear();
156 for (Map.Entry<Object, Method[]> entry : listeners.entrySet()) {
a4524c1b 157 List<Method> matchingMethods = new ArrayList<>();
d5c13688
FC
158 for (Method method : entry.getValue()) {
159 if (method.getParameterTypes()[0].isAssignableFrom(signalClass)) {
160 matchingMethods.add(method);
161 }
162 }
163 if (!matchingMethods.isEmpty()) {
164 targets.put(entry.getKey(), matchingMethods);
165 }
166 }
167
6256d8ad 168 // Call the signal handlers
d5c13688
FC
169 for (Map.Entry<Object, List<Method>> entry : targets.entrySet()) {
170 for (Method method : entry.getValue()) {
171 try {
172 method.invoke(entry.getKey(), new Object[] { signal });
5500a7f0 173 if (TmfCoreTracer.isSignalTraced()) {
d5c13688
FC
174 Object key = entry.getKey();
175 String hash = String.format("%1$08X", entry.getKey().hashCode()); //$NON-NLS-1$
176 String target = "[" + hash + "] " + key.getClass().getSimpleName() + ":" + method.getName(); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
5500a7f0 177 TmfCoreTracer.traceSignal(signal, target);
d5c13688
FC
178 }
179 } catch (IllegalArgumentException e) {
5500a7f0 180 Activator.logError("Exception handling signal " + signal + " in method " + method, e); //$NON-NLS-1$ //$NON-NLS-2$
d5c13688 181 } catch (IllegalAccessException e) {
5500a7f0 182 Activator.logError("Exception handling signal " + signal + " in method " + method, e); //$NON-NLS-1$ //$NON-NLS-2$
d5c13688 183 } catch (InvocationTargetException e) {
5500a7f0 184 Activator.logError("Exception handling signal " + signal + " in method " + method, e); //$NON-NLS-1$ //$NON-NLS-2$
d5c13688
FC
185 }
186 }
187 }
188
5500a7f0
FC
189 if (TmfCoreTracer.isSignalTraced()) {
190 TmfCoreTracer.traceSignal(signal, "(end)"); //$NON-NLS-1$
6256d8ad 191 }
d5c13688 192 }
dc299841 193
dc299841 194}
This page took 0.055062 seconds and 5 git commands to generate.