blob: 854baa4706b2477cdc5872d5d1aade5ba28dc65b [file] [log] [blame]
Richard S. Hallddf2e142009-09-30 17:03:45 +00001/*
Richard S. Hall0b8e3ba2006-10-25 13:26:32 +00002 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Richard S. Hall44002cf2009-02-11 21:47:26 +000019package org.apache.felix.log;
Richard S. Hall0b8e3ba2006-10-25 13:26:32 +000020
Richard S. Hall7d552dc2011-03-24 19:31:41 +000021import java.util.ArrayList;
Richard S. Hall0b8e3ba2006-10-25 13:26:32 +000022import java.util.Iterator;
23import java.util.List;
Richard S. Hall0b8e3ba2006-10-25 13:26:32 +000024
25import org.osgi.service.log.LogEntry;
26import org.osgi.service.log.LogListener;
27
28/**
29 * This class is responsible for asynchronously delivering log messages to
30 * any {@link LogListener} subscribers. A subscriber can be added using the
31 * {@link org.osgi.service.log.LogReaderService#addLogListener(LogListener)}
32 * method.
33 */
Richard S. Hallddf2e142009-09-30 17:03:45 +000034final class LogListenerThread extends Thread
35{
Richard S. Hall7d552dc2011-03-24 19:31:41 +000036 // The list of entries waiting to be delivered to the log listeners.
37 private final List m_entriesToDeliver = new ArrayList();
38 // The list of listeners.
39 private final List m_listeners = new ArrayList();
Richard S. Hall0b8e3ba2006-10-25 13:26:32 +000040
Felix Meschberger0d77a052012-07-03 09:18:03 +000041 LogListenerThread() {
42 super("FelixLogListener");
43 }
44
Richard S. Hall0b8e3ba2006-10-25 13:26:32 +000045 /**
46 * Add an entry to the list of messages to deliver.
47 * @param entry the log entry to deliver
48 */
Richard S. Hallddf2e142009-09-30 17:03:45 +000049 void addEntry(final LogEntry entry)
50 {
51 synchronized (m_entriesToDeliver)
52 {
Richard S. Hall0b8e3ba2006-10-25 13:26:32 +000053 m_entriesToDeliver.add(entry);
54 m_entriesToDeliver.notifyAll();
55 }
56 }
57
58 /**
59 * Add a listener to the list of listeners that are subscribed.
60 * @param listener the listener to add to the list of subscribed listeners
61 */
Richard S. Hallddf2e142009-09-30 17:03:45 +000062 void addListener(final LogListener listener)
63 {
64 synchronized (m_listeners)
65 {
Richard S. Hall0b8e3ba2006-10-25 13:26:32 +000066 m_listeners.add(listener);
67 }
68 }
69
70 /**
71 * Remove a listener from the list of listeners that are subscribed.
72 * @param listener the listener to remove from the list of subscribed listeners
73 */
Richard S. Hallddf2e142009-09-30 17:03:45 +000074 void removeListener(final LogListener listener)
75 {
76 synchronized (m_listeners)
77 {
Richard S. Hall0b8e3ba2006-10-25 13:26:32 +000078 m_listeners.remove(listener);
79 }
80 }
81
82 /**
83 * Returns the number of listeners that are currently registered.
84 * @return the number of listeners that are currently registered
85 */
Richard S. Hallddf2e142009-09-30 17:03:45 +000086 int getListenerCount()
87 {
Jan Willem Janssenaecb08e2012-08-08 08:50:34 +000088 synchronized (m_listeners)
89 {
90 return m_listeners.size();
91 }
Richard S. Hall0b8e3ba2006-10-25 13:26:32 +000092 }
93
94 /**
95 * Stop the thread. This will happen asynchronously.
96 */
Richard S. Hallddf2e142009-09-30 17:03:45 +000097 void shutdown()
98 {
Richard S. Hallddf2e142009-09-30 17:03:45 +000099 synchronized (m_entriesToDeliver)
100 {
Jan Willem Janssenaecb08e2012-08-08 08:50:34 +0000101 interrupt();
Richard S. Hall0b8e3ba2006-10-25 13:26:32 +0000102 }
103 }
104
105 /**
106 * The main method of the thread: waits for new messages to be receieved
107 * and then delivers them to any registered log listeners.
108 */
Richard S. Hallddf2e142009-09-30 17:03:45 +0000109 public void run()
110 {
Jan Willem Janssenaecb08e2012-08-08 08:50:34 +0000111 while (!isInterrupted())
Richard S. Hallddf2e142009-09-30 17:03:45 +0000112 {
Jan Willem Janssenaecb08e2012-08-08 08:50:34 +0000113 List entriesToDeliver = new ArrayList();
Richard S. Hallddf2e142009-09-30 17:03:45 +0000114 synchronized (m_entriesToDeliver)
115 {
Richard S. Hallddf2e142009-09-30 17:03:45 +0000116 if (m_entriesToDeliver.isEmpty())
117 {
118 try
119 {
Richard S. Hall0b8e3ba2006-10-25 13:26:32 +0000120 m_entriesToDeliver.wait();
Richard S. Hallddf2e142009-09-30 17:03:45 +0000121 }
122 catch (InterruptedException e)
123 {
Jan Willem Janssenaecb08e2012-08-08 08:50:34 +0000124 // the interrupt-flag is cleared; so, let's play nice and
125 // interrupt this thread again to stop it...
126 interrupt();
Richard S. Hall0b8e3ba2006-10-25 13:26:32 +0000127 }
128 }
Jan Willem Janssenaecb08e2012-08-08 08:50:34 +0000129 else
130 {
131 // Copy all current entries and deliver them in a single go...
132 entriesToDeliver.addAll(m_entriesToDeliver);
133 m_entriesToDeliver.clear();
134 }
Richard S. Hall0b8e3ba2006-10-25 13:26:32 +0000135 }
Jan Willem Janssenaecb08e2012-08-08 08:50:34 +0000136
137 if (!entriesToDeliver.isEmpty())
Richard S. Hallddf2e142009-09-30 17:03:45 +0000138 {
Jan Willem Janssenaecb08e2012-08-08 08:50:34 +0000139 // Take a snapshot of all current listeners and deliver all
140 // pending messages to them...
141 List listeners = new ArrayList();
142 synchronized (m_listeners)
143 {
144 listeners.addAll(m_listeners);
145 }
146
147 Iterator entriesIt = entriesToDeliver.iterator();
148 while (entriesIt.hasNext())
149 {
150 LogEntry entry = (LogEntry) entriesIt.next();
151
152 Iterator listenerIt = listeners.iterator();
153 while (listenerIt.hasNext())
154 {
155 LogListener listener = (LogListener) listenerIt.next();
156
157 try
158 {
159 listener.logged(entry);
160 }
161 catch (Throwable t)
162 {
163 // catch and discard any exceptions thrown by the listener
164 }
165 }
166 }
Richard S. Hall0b8e3ba2006-10-25 13:26:32 +0000167 }
168 }
169 }
Richard S. Hallddf2e142009-09-30 17:03:45 +0000170}