Skip to content

Package: EventQueue$TerminatorEvent

EventQueue$TerminatorEvent

nameinstructionbranchcomplexitylinemethod
EventQueue.TerminatorEvent()
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
dispatch(Object)
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved.
3: *
4: * This program and the accompanying materials are made available under the
5: * terms of the Eclipse Public License v. 2.0, which is available at
6: * http://www.eclipse.org/legal/epl-2.0.
7: *
8: * This Source Code may also be made available under the following Secondary
9: * Licenses when the conditions for such availability set forth in the
10: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11: * version 2 with the GNU Classpath Exception, which is available at
12: * https://www.gnu.org/software/classpath/license.html.
13: *
14: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15: */
16:
17: package jakarta.mail;
18:
19: import jakarta.mail.event.MailEvent;
20:
21: import java.util.EventListener;
22: import java.util.Vector;
23: import java.util.WeakHashMap;
24: import java.util.concurrent.BlockingQueue;
25: import java.util.concurrent.Executor;
26: import java.util.concurrent.LinkedBlockingQueue;
27:
28: /**
29: * Package private class used by Store & Folder to dispatch events.
30: * This class implements an event queue, and a dispatcher thread that
31: * dequeues and dispatches events from the queue.
32: *
33: * @author Bill Shannon
34: */
35: class EventQueue implements Runnable {
36:
37: private volatile BlockingQueue<QueueElement> q;
38: private Executor executor;
39:
40: private static WeakHashMap<ClassLoader, EventQueue> appq;
41:
42: /**
43: * A special event that causes the queue processing task to terminate.
44: */
45: static class TerminatorEvent extends MailEvent {
46: private static final long serialVersionUID = -2481895000841664111L;
47:
48: TerminatorEvent() {
49: super(new Object());
50: }
51:
52: @Override
53: public void dispatch(Object listener) {
54: // Kill the event dispatching thread.
55: Thread.currentThread().interrupt();
56: }
57: }
58:
59: /**
60: * A "struct" to put on the queue.
61: */
62: static class QueueElement {
63: MailEvent event = null;
64: Vector<? extends EventListener> vector = null;
65:
66: QueueElement(MailEvent event, Vector<? extends EventListener> vector) {
67: this.event = event;
68: this.vector = vector;
69: }
70: }
71:
72: /**
73: * Construct an EventQueue using the specified Executor.
74: * If the Executor is null, threads will be created as needed.
75: */
76: EventQueue(Executor ex) {
77: this.executor = ex;
78: }
79:
80: /**
81: * Enqueue an event.
82: */
83: synchronized void enqueue(MailEvent event,
84: Vector<? extends EventListener> vector) {
85: // if this is the first event, create the queue and start the event task
86: if (q == null) {
87: q = new LinkedBlockingQueue<>();
88: if (executor != null) {
89: executor.execute(this);
90: } else {
91: Thread qThread = new Thread(this, "Jakarta-Mail-EventQueue");
92: qThread.setDaemon(true); // not a user thread
93: qThread.start();
94: }
95: }
96: q.add(new QueueElement(event, vector));
97: }
98:
99: /**
100: * Terminate the task running the queue, but only if there is a queue.
101: */
102: synchronized void terminateQueue() {
103: if (q != null) {
104: Vector<EventListener> dummyListeners = new Vector<>();
105: dummyListeners.setSize(1); // need atleast one listener
106: q.add(new QueueElement(new TerminatorEvent(), dummyListeners));
107: q = null;
108: }
109: }
110:
111: /**
112: * Create (if necessary) an application-scoped event queue.
113: * Application scoping is based on the thread's context class loader.
114: */
115: static synchronized EventQueue getApplicationEventQueue(Executor ex) {
116: ClassLoader cl = Session.getContextClassLoader();
117: if (appq == null)
118: appq = new WeakHashMap<>();
119: EventQueue q = appq.get(cl);
120: if (q == null) {
121: q = new EventQueue(ex);
122: appq.put(cl, q);
123: }
124: return q;
125: }
126:
127: /**
128: * Pull events off the queue and dispatch them.
129: */
130: @Override
131: public void run() {
132:
133: BlockingQueue<QueueElement> bq = q;
134: if (bq == null)
135: return;
136: try {
137: loop:
138: for (; ; ) {
139: // block until an item is available
140: QueueElement qe = bq.take();
141: MailEvent e = qe.event;
142: Vector<? extends EventListener> v = qe.vector;
143:
144: for (int i = 0; i < v.size(); i++)
145: try {
146: e.dispatch(v.elementAt(i));
147: } catch (Throwable t) {
148: if (t instanceof InterruptedException)
149: break loop;
150: // ignore anything else thrown by the listener
151: }
152:
153: qe = null;
154: e = null;
155: v = null;
156: }
157: } catch (InterruptedException e) {
158: // just die
159: }
160: }
161: }