Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.management/share/classes/sun/management/NotificationEmitterSupport.java
41152 views
1
/*
2
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.management;
27
28
import javax.management.ListenerNotFoundException;
29
import javax.management.MBeanNotificationInfo;
30
import javax.management.Notification;
31
import javax.management.NotificationEmitter;
32
import javax.management.NotificationFilter;
33
import javax.management.NotificationListener;
34
35
import java.util.List;
36
import java.util.ArrayList;
37
import java.util.Collections;
38
39
/**
40
* Abstract helper class for notification emitter support.
41
*/
42
public abstract class NotificationEmitterSupport implements NotificationEmitter {
43
44
protected NotificationEmitterSupport() {
45
}
46
47
private Object listenerLock = new Object();
48
49
// Implementation of NotificationEmitter interface
50
// Cloned from JMX NotificationBroadcasterSupport class.
51
public void addNotificationListener(NotificationListener listener,
52
NotificationFilter filter,
53
Object handback) {
54
55
if (listener == null) {
56
throw new IllegalArgumentException ("Listener can't be null") ;
57
}
58
59
/* Adding a new listener takes O(n) time where n is the number
60
of existing listeners. If you have a very large number of
61
listeners performance could degrade. That's a fairly
62
surprising configuration, and it is hard to avoid this
63
behaviour while still retaining the property that the
64
listenerList is not synchronized while notifications are
65
being sent through it. If this becomes a problem, a
66
possible solution would be a multiple-readers single-writer
67
setup, so any number of sendNotification() calls could run
68
concurrently but they would exclude an
69
add/removeNotificationListener. A simpler but less
70
efficient solution would be to clone the listener list
71
every time a notification is sent. */
72
synchronized (listenerLock) {
73
List<ListenerInfo> newList = new ArrayList<>(listenerList.size() + 1);
74
newList.addAll(listenerList);
75
newList.add(new ListenerInfo(listener, filter, handback));
76
listenerList = newList;
77
}
78
}
79
80
public void removeNotificationListener(NotificationListener listener)
81
throws ListenerNotFoundException {
82
83
synchronized (listenerLock) {
84
List<ListenerInfo> newList = new ArrayList<>(listenerList);
85
/* We scan the list of listeners in reverse order because
86
in forward order we would have to repeat the loop with
87
the same index after a remove. */
88
for (int i=newList.size()-1; i>=0; i--) {
89
ListenerInfo li = newList.get(i);
90
91
if (li.listener == listener)
92
newList.remove(i);
93
}
94
if (newList.size() == listenerList.size())
95
throw new ListenerNotFoundException("Listener not registered");
96
listenerList = newList;
97
}
98
}
99
100
public void removeNotificationListener(NotificationListener listener,
101
NotificationFilter filter,
102
Object handback)
103
throws ListenerNotFoundException {
104
105
boolean found = false;
106
107
synchronized (listenerLock) {
108
List<ListenerInfo> newList = new ArrayList<>(listenerList);
109
final int size = newList.size();
110
for (int i = 0; i < size; i++) {
111
ListenerInfo li = newList.get(i);
112
113
if (li.listener == listener) {
114
found = true;
115
if (li.filter == filter
116
&& li.handback == handback) {
117
newList.remove(i);
118
listenerList = newList;
119
return;
120
}
121
}
122
}
123
}
124
125
if (found) {
126
/* We found this listener, but not with the given filter
127
* and handback. A more informative exception message may
128
* make debugging easier. */
129
throw new ListenerNotFoundException("Listener not registered " +
130
"with this filter and " +
131
"handback");
132
} else {
133
throw new ListenerNotFoundException("Listener not registered");
134
}
135
}
136
137
public void sendNotification(Notification notification) {
138
139
if (notification == null) {
140
return;
141
}
142
143
List<ListenerInfo> currentList;
144
synchronized (listenerLock) {
145
currentList = listenerList;
146
}
147
148
final int size = currentList.size();
149
for (int i = 0; i < size; i++) {
150
ListenerInfo li = currentList.get(i);
151
152
if (li.filter == null
153
|| li.filter.isNotificationEnabled(notification)) {
154
try {
155
li.listener.handleNotification(notification, li.handback);
156
} catch (Exception e) {
157
e.printStackTrace();
158
throw new AssertionError("Error in invoking listener");
159
}
160
}
161
}
162
}
163
164
public boolean hasListeners() {
165
synchronized (listenerLock) {
166
return !listenerList.isEmpty();
167
}
168
}
169
170
private class ListenerInfo {
171
public NotificationListener listener;
172
NotificationFilter filter;
173
Object handback;
174
175
public ListenerInfo(NotificationListener listener,
176
NotificationFilter filter,
177
Object handback) {
178
this.listener = listener;
179
this.filter = filter;
180
this.handback = handback;
181
}
182
}
183
184
/**
185
* Current list of listeners, a List of ListenerInfo. The object
186
* referenced by this field is never modified. Instead, the field
187
* is set to a new object when a listener is added or removed,
188
* within a synchronized(this). In this way, there is no need to
189
* synchronize when traversing the list to send a notification to
190
* the listeners in it. That avoids potential deadlocks if the
191
* listeners end up depending on other threads that are themselves
192
* accessing this NotificationBroadcasterSupport.
193
*/
194
private List<ListenerInfo> listenerList = Collections.emptyList();
195
196
abstract public MBeanNotificationInfo[] getNotificationInfo();
197
}
198
199