Commit | Line | Data |
---|---|---|
8c8bf09f | 1 | /******************************************************************************* |
50adc88e | 2 | * Copyright (c) 2009 Ericsson |
8c8bf09f ASL |
3 | * |
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 | |
8 | * | |
9 | * Contributors: | |
10 | * Francois Chouinard - Initial API and implementation | |
11 | *******************************************************************************/ | |
12 | ||
13 | package org.eclipse.linuxtools.tmf.signal; | |
14 | ||
15 | import java.lang.reflect.InvocationTargetException; | |
16 | import java.lang.reflect.Method; | |
17 | import java.util.ArrayList; | |
18 | import java.util.HashMap; | |
19 | import java.util.List; | |
20 | import java.util.Map; | |
21 | ||
22 | /** | |
23 | * <b><u>TmfSignalHandler</u></b> | |
24 | * <p> | |
50adc88e | 25 | * TODO: Implement me. Please. |
8c8bf09f | 26 | * <p> |
50adc88e | 27 | * TODO: Error/exception handling |
8c8bf09f ASL |
28 | */ |
29 | public class TmfSignalManager { | |
30 | ||
50adc88e FC |
31 | /** |
32 | * The set of event listeners and their corresponding handler methods. | |
50adc88e | 33 | */ |
8c8bf09f ASL |
34 | static private Map<Object, Method[]> fListeners = new HashMap<Object, Method[]>(); |
35 | ||
82b08e62 FC |
36 | // TODO: read from the preferences |
37 | private static boolean fTraceIsActive = true; | |
38 | private static TmfSignalTrace fSignalTracer; | |
39 | ||
40 | private static TmfSignalManager fInstance; | |
41 | ||
42 | static { | |
43 | if (fTraceIsActive) { | |
44 | fSignalTracer = new TmfSignalTrace(); | |
45 | addListener(fSignalTracer); | |
46 | } | |
47 | } | |
8c8bf09f | 48 | |
82b08e62 | 49 | public static synchronized void addListener(Object listener) { |
8c8bf09f ASL |
50 | Method[] methods = getSignalHandlerMethods(listener); |
51 | if (methods.length > 0) | |
82b08e62 | 52 | fListeners.put(listener, methods); |
8c8bf09f ASL |
53 | } |
54 | ||
82b08e62 FC |
55 | public static synchronized void removeListener(Object listener) { |
56 | fListeners.remove(listener); | |
8c8bf09f ASL |
57 | } |
58 | ||
82b08e62 FC |
59 | public static TmfSignalManager getInstance() { |
60 | if (fInstance == null) { | |
61 | fInstance = new TmfSignalManager(); | |
62 | } | |
63 | return fInstance; | |
64 | } | |
8c8bf09f | 65 | /** |
50adc88e | 66 | * Invokes the handling methods that expect this signal. |
8c8bf09f ASL |
67 | * |
68 | * The list of handlers is built on-the-fly to allow for the dynamic | |
69 | * creation/deletion of signal handlers. Since the number of signal | |
70 | * handlers shouldn't be too high, this is not a big performance issue | |
71 | * to pay for the flexibility. | |
72 | * | |
50adc88e | 73 | * @param signal |
8c8bf09f | 74 | */ |
82b08e62 FC |
75 | private class Dispatch implements Runnable { |
76 | ||
77 | private final Method method; | |
78 | private final Object entry; | |
79 | private final Object signal; | |
80 | ||
81 | public Dispatch(Method m, Object e, Object s) { | |
82 | method = m; | |
83 | entry = e; | |
84 | signal = s; | |
85 | } | |
86 | ||
87 | public void run() { | |
88 | try { | |
89 | method.invoke(entry, new Object[] { signal }); | |
90 | } catch (IllegalArgumentException e) { | |
91 | // TODO Auto-generated catch block | |
92 | e.printStackTrace(); | |
93 | } catch (IllegalAccessException e) { | |
94 | // TODO Auto-generated catch block | |
95 | e.printStackTrace(); | |
96 | } catch (InvocationTargetException e) { | |
97 | // TODO Auto-generated catch block | |
98 | e.printStackTrace(); | |
99 | } | |
100 | } | |
101 | } | |
102 | ||
103 | private void dispatch(Method method, Object key, Object signal) { | |
104 | Dispatch disp = new Dispatch(method, key, signal); | |
105 | new Thread(disp).start(); | |
106 | } | |
107 | ||
108 | static public synchronized void dispatchSignal(Object signal) { | |
8c8bf09f ASL |
109 | |
110 | // Build the list of listener methods that are registered for this signal | |
111 | Class<?> signalClass = signal.getClass(); | |
112 | Map<Object, List<Method>> listeners = new HashMap<Object, List<Method>>(); | |
82b08e62 | 113 | listeners.clear(); |
8c8bf09f | 114 | for (Map.Entry<Object, Method[]> entry : fListeners.entrySet()) { |
82b08e62 | 115 | List<Method> matchingMethods = new ArrayList<Method>(); |
8c8bf09f ASL |
116 | for (Method method : entry.getValue()) { |
117 | if (method.getParameterTypes()[0].isAssignableFrom(signalClass)) { | |
118 | matchingMethods.add(method); | |
119 | } | |
120 | } | |
121 | if (!matchingMethods.isEmpty()) { | |
122 | listeners.put(entry.getKey(), matchingMethods); | |
123 | } | |
124 | } | |
125 | ||
50adc88e | 126 | // Call the signal handlers |
8c8bf09f ASL |
127 | for (Map.Entry<Object, List<Method>> entry : listeners.entrySet()) { |
128 | for (Method method : entry.getValue()) { | |
82b08e62 FC |
129 | getInstance().dispatch(method, entry.getKey(), signal); |
130 | // try { | |
131 | // method.invoke(entry.getKey(), new Object[] { signal }); | |
132 | // } catch (IllegalArgumentException e) { | |
133 | // // TODO Auto-generated catch block | |
134 | // e.printStackTrace(); | |
135 | // } catch (IllegalAccessException e) { | |
136 | // // TODO Auto-generated catch block | |
137 | // e.printStackTrace(); | |
138 | // } catch (InvocationTargetException e) { | |
139 | // // TODO Auto-generated catch block | |
140 | // e.printStackTrace(); | |
141 | // } | |
8c8bf09f ASL |
142 | } |
143 | } | |
144 | } | |
145 | ||
50adc88e FC |
146 | /** |
147 | * Returns the list of signal handlers in the listener. Signal handler name | |
148 | * is irrelevant; only the annotation (@TmfSignalHandler) is important. | |
149 | * | |
150 | * @param listener | |
151 | * @return | |
152 | */ | |
153 | static private Method[] getSignalHandlerMethods(Object listener) { | |
154 | List<Method> handlers = new ArrayList<Method>(); | |
155 | Method[] methods = listener.getClass().getMethods(); | |
156 | for (Method method : methods) { | |
157 | if (method.isAnnotationPresent(TmfSignalHandler.class)) { | |
158 | handlers.add(method); | |
159 | } | |
160 | } | |
161 | return handlers.toArray(new Method[handlers.size()]); | |
162 | } | |
163 | ||
164 | } |