Skip to content

Commit 02998ee

Browse files
committed
Vendor the org.bushe:eventbus library
We need to fix a bug, but the upstream library is not actively maintained anymore. Including the code in scijava-common makes it easier to make changes to the codebase directly.
1 parent c5202ad commit 02998ee

File tree

103 files changed

+12679
-20
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+12679
-20
lines changed

pom.xml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@
167167
<license.licenseName>bsd_2</license.licenseName>
168168
<license.projectName>SciJava Common shared library for SciJava software.</license.projectName>
169169
<license.copyrightOwners>SciJava developers.</license.copyrightOwners>
170+
<license.excludes>**/bushe/**</license.excludes>
170171
</properties>
171172

172173
<dependencies>
@@ -176,13 +177,6 @@
176177
<artifactId>parsington</artifactId>
177178
</dependency>
178179

179-
<!-- Third-party dependencies -->
180-
<dependency>
181-
<groupId>org.bushe</groupId>
182-
<artifactId>eventbus</artifactId>
183-
<version>1.4</version>
184-
</dependency>
185-
186180
<!-- Test scope dependencies -->
187181
<dependency>
188182
<groupId>junit</groupId>
@@ -193,7 +187,7 @@
193187
<groupId>org.mockito</groupId>
194188
<artifactId>mockito-core</artifactId>
195189
<scope>test</scope>
196-
</dependency>
190+
</dependency>
197191
</dependencies>
198192

199193
<build>

src/main/java/org/scijava/event/DefaultEventBus.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,18 @@
3434
import java.util.Arrays;
3535
import java.util.List;
3636

37-
import org.bushe.swing.event.CleanupEvent;
38-
import org.bushe.swing.event.ThreadSafeEventService;
37+
import org.scijava.event.bushe.CleanupEvent;
38+
import org.scijava.event.bushe.ThreadSafeEventService;
3939
import org.scijava.log.LogService;
4040
import org.scijava.service.Service;
4141
import org.scijava.thread.ThreadService;
4242

4343
/**
44-
* An {@link org.bushe.swing.event.EventService} implementation for SciJava.
44+
* An {@link org.scijava.event.bushe.EventService} implementation for SciJava.
4545
* <p>
4646
* It is called "DefaultEventBus" rather than "DefaultEventService" to avoid a
4747
* name clash with {@link DefaultEventService}, which is not an
48-
* {@link org.bushe.swing.event.EventService} but rather a SciJava
48+
* {@link org.scijava.event.bushe.EventService} but rather a SciJava
4949
* {@link Service} implementation.
5050
* </p>
5151
*
@@ -112,7 +112,7 @@ public void publishLater(final String topicName, final Object eventObj) {
112112
getVetoEventListeners(topicName), null);
113113
}
114114

115-
// -- org.bushe.swing.event.EventService methods --
115+
// -- org.scijava.event.bushe.EventService methods --
116116

117117
@Override
118118
public void publish(final Object event) {

src/main/java/org/scijava/event/DefaultEventService.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@
4040
import java.util.Map;
4141
import java.util.WeakHashMap;
4242

43-
import org.bushe.swing.event.annotation.AbstractProxySubscriber;
44-
import org.bushe.swing.event.annotation.BaseProxySubscriber;
45-
import org.bushe.swing.event.annotation.ReferenceStrength;
43+
import org.scijava.event.bushe.annotation.AbstractProxySubscriber;
44+
import org.scijava.event.bushe.annotation.BaseProxySubscriber;
45+
import org.scijava.event.bushe.annotation.ReferenceStrength;
4646
import org.scijava.Priority;
4747
import org.scijava.log.LogService;
4848
import org.scijava.plugin.Parameter;
@@ -263,7 +263,7 @@ private synchronized void keepIt(final Object o, final ProxySubscriber<?> subscr
263263
* Helper class used by {@link #subscribe(Object)}.
264264
* <p>
265265
* Recapitulates some logic from {@link BaseProxySubscriber}, because that
266-
* class implements {@link org.bushe.swing.event.EventSubscriber} as a raw
266+
* class implements {@link org.scijava.event.bushe.EventSubscriber} as a raw
267267
* type, which is incompatible with this class implementing SciJava's
268268
* {@link EventSubscriber} as a typed interface; it becomes impossible to
269269
* implement both {@code onEvent(Object)} and {@code onEvent(E)}.

src/main/java/org/scijava/event/EventHandler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@
4040
* handling methods and annotating each with @{@link EventHandler}.
4141
* <p>
4242
* Note to developers: This annotation serves exactly the same purpose as
43-
* EventBus's {@link org.bushe.swing.event.annotation.EventSubscriber}
43+
* EventBus's {@link org.scijava.event.bushe.annotation.EventSubscriber}
4444
* annotation, recapitulating a subset of the same functionality. We do this to
4545
* avoid third party code depending directly on EventBus. That is, we do not
46-
* wish to require SciJava developers to {@code import org.bushe.swing.event.*}
46+
* wish to require SciJava developers to {@code import org.scijava.event.bushe.*}
4747
* or similar. In this way, EventBus is isolated as only a transitive dependency
4848
* of downstream code, rather than a direct dependency. Unfortunately, because
4949
* Java annotation interfaces cannot utilize inheritance, we have to

src/main/java/org/scijava/event/EventSubscriber.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
* @param <E> Type of event for which to listen
4545
*/
4646
public interface EventSubscriber<E extends SciJavaEvent> extends
47-
org.bushe.swing.event.EventSubscriber<E>
47+
org.scijava.event.bushe.EventSubscriber<E>
4848
{
4949

5050
@Override
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* Copyright 2005 Bushe Enterprises, Inc., Hopkinton, MA, USA, www.bushe.com
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.scijava.event.bushe;
17+
18+
/**
19+
* Convenience base class for EventServiceEvents in the application. Provides the convenience of
20+
* holding the event source publication and event status. It is not necessary to use this event class when
21+
* using an EventService.
22+
*
23+
* @author Michael Bushe michael@bushe.com
24+
*/
25+
public abstract class AbstractEventServiceEvent implements EventServiceEvent, PublicationStatusTracker {
26+
27+
private Object source = null;
28+
protected final Object stateLock = new Object();
29+
private PublicationStatus publicationStatus = PublicationStatus.Unpublished;
30+
31+
/**
32+
* Default constructor
33+
*
34+
* @param source the source of the event
35+
*/
36+
public AbstractEventServiceEvent(Object source) {
37+
this.source = source;
38+
}
39+
40+
/** @return the source of this event */
41+
public Object getSource() {
42+
return source;
43+
}
44+
45+
public PublicationStatus getPublicationStatus() {
46+
synchronized (stateLock) {
47+
return publicationStatus;
48+
}
49+
}
50+
51+
public void setPublicationStatus(PublicationStatus status) {
52+
synchronized (stateLock) {
53+
publicationStatus = status;
54+
}
55+
}
56+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* Copyright 2007 Bushe Enterprises, Inc., Hopkinton, MA, USA, www.bushe.com
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.scijava.event.bushe;
17+
18+
/**
19+
* Published when the ThreadSafeEventService cleans up stale subscribers.
20+
* @author Michael Bushe
21+
*/
22+
public class CleanupEvent {
23+
24+
/** The status of the cleanup.*/
25+
public enum Status {
26+
/** Timer has started the cleanup task. Will be followed by at least one more CleanupEvent.*/
27+
STARTING,
28+
/** Task has determined there's cleanup to do.*/
29+
OVER_STOP_THRESHOLD_CLEANING_BEGUN,
30+
/** Task has determined there's no cleanup to do.*/
31+
UNDER_STOP_THRESHOLD_CLEANING_CANCELLED,
32+
/** Finished cleaning up task.*/
33+
FINISHED_CLEANING;
34+
}
35+
36+
private Status status;
37+
private int totalWeakRefsAndProxies;
38+
private Integer numStaleSubscribersCleaned;
39+
40+
public CleanupEvent(Status status, int totalWeakRefsAndProxies, Integer numStaleSubscribersCleaned) {
41+
this.status = status;
42+
this.totalWeakRefsAndProxies = totalWeakRefsAndProxies;
43+
this.numStaleSubscribersCleaned = numStaleSubscribersCleaned;
44+
}
45+
46+
public Status getStatus() {
47+
return status;
48+
}
49+
50+
/** Total weak refs and ProxySubscribers subscribed. */
51+
public int getTotalWeakRefsAndProxies() {
52+
return totalWeakRefsAndProxies;
53+
}
54+
55+
/**
56+
* Null unless status is FINISHED_CLEANING.
57+
* @return the number of stale subscribers cleaned during the cleanup run.
58+
*/
59+
public Integer getNumStaleSubscribersCleaned() {
60+
return numStaleSubscribersCleaned;
61+
}
62+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* Copyright 2005 Bushe Enterprises, Inc., Hopkinton, MA, USA, www.bushe.com
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.scijava.event.bushe;
17+
18+
import java.awt.Component;
19+
import java.awt.event.ActionEvent;
20+
import javax.swing.ImageIcon;
21+
22+
/**
23+
* When fired, this action publishes an ActionEvent on a Container EventService.
24+
* See {@link EventServiceAction} for more information.
25+
* <p/>
26+
* By default, the Container EventService is found by asking the ContainerEventServiceFinder to find the EventService
27+
* for the source of the fired ActionEvent, which must be a java.awt.Component and contained in a hierarchy (the source
28+
* must have been added to another Swing container). If the action was on a button, this means the container hierarchy
29+
* of the button is walked (up) until a ContainerEventServiceSupplier is found or until the top of the hierarchy is
30+
* reached, at which point a ContainerEventService is created automatically on the fly via the top container's
31+
* putClientProperty() method using the key {@link ContainerEventServiceFinder#CLIENT_PROPERTY_KEY_TOP_LEVEL_EVENT_SERVICE}.
32+
* If the event is from a JPopupMenu then the popup menu's invoker's hierarchy is walked.
33+
* <p/>
34+
* To exhibit other behavior, override the getSwingEventService() to return another EventService. For example, the
35+
* creator of a popup menu may pass itself to the ContainerEventServiceFinder to return a parent's EventService.
36+
* <p/>
37+
*
38+
* @author Michael Bushe michael@bushe.com
39+
* @see EventServiceAction for further documentation
40+
* @see ContainerEventServiceFinder on how the service is found
41+
*/
42+
public class ContainerEventServiceAction extends EventServiceAction {
43+
public ContainerEventServiceAction() {
44+
}
45+
46+
public ContainerEventServiceAction(String actionName, ImageIcon icon) {
47+
super(actionName, icon);
48+
}
49+
50+
protected EventService getEventService(ActionEvent event) {
51+
Component comp = null;
52+
try {
53+
if (event.getSource() instanceof Component) {
54+
comp = (Component) event.getSource();
55+
}
56+
if (comp == null) {
57+
if (getThrowsExceptionOnNullEventService()) {
58+
throw new RuntimeException("ActionEvent source was null, could not find event bus, must override getContainerEventService in action with id:" + getName());
59+
}
60+
} else {
61+
return ContainerEventServiceFinder.getEventService(comp);
62+
}
63+
} catch (ClassCastException ex) {
64+
if (getThrowsExceptionOnNullEventService()) {
65+
throw new RuntimeException("ActionEvent source was not a component (" + (comp == null ? "null" : comp.getClass() + "") + "), must override getContainerEventService in action with id:" + getName(), ex);
66+
}
67+
}
68+
return null;
69+
}
70+
}
71+
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/**
2+
* Copyright 2005 Bushe Enterprises, Inc., Hopkinton, MA, USA, www.bushe.com
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.scijava.event.bushe;
17+
18+
import java.awt.Component;
19+
import javax.swing.JComponent;
20+
import javax.swing.JPopupMenu;
21+
import javax.swing.RootPaneContainer;
22+
23+
/**
24+
* This class finds a component's container event service, and creates one if necessary and possible.
25+
* <p/>
26+
* A Container EventService is, unlike the EventBus, an EventService that is container specific, in other words, it is
27+
* shared only amongst components within a container. For example, a Form component can supply an EventService used
28+
* only by components in the form. The Form's components can publish value change events on their Container's Event
29+
* Service. The Form's Model and Validator may listen to these events to collect data and show errors, respectively.
30+
* <p/>
31+
* Most importantly, Container EventService's cuts down event traffic, avoid naming and listener clashes, promotes
32+
* componentization, and splits events usage into logical subsets.
33+
* <p/>
34+
* The finder will walk up a component's hierarchy searching for a parent that implements ContainerEventServiceSupplier.
35+
* If it find one, it returns it. If it doesn't find one, the top level JComponent (specifically, the highest parent in
36+
* the hierarchy, typically a JRootPane) has a client property added to it (if not already set) that has the value of a
37+
* new SwingEventService, which is then returned. The EventBus is never returned.
38+
*
39+
* @author Michael Bushe michael@bushe.com
40+
*/
41+
public class ContainerEventServiceFinder {
42+
/** The client property used to put a new SwingEventService on top-level components. */
43+
public static final String CLIENT_PROPERTY_KEY_TOP_LEVEL_EVENT_SERVICE = "ContainerEventServiceFinder.createdService";
44+
45+
/**
46+
* Walks the component's parents until it find an ContainerEventServiceSupplier and returns the supplier's
47+
* EventService. If the component in the tree is a JPopupMenu, then the menu's invoker is walked.
48+
*
49+
* @param component any component
50+
*
51+
* @return the ContainerEventService of the nearest parent
52+
*/
53+
public static EventService getEventService(Component component) {
54+
while (component != null) {
55+
if (component instanceof ContainerEventServiceSupplier) {
56+
return ((ContainerEventServiceSupplier) component).getContainerEventService();
57+
}
58+
if (component instanceof JPopupMenu) {
59+
component = ((JPopupMenu) component).getInvoker();
60+
} else {
61+
if (component.getParent() == null) {
62+
//There is no supplier. Instead of returning null, make an event service
63+
//and stick it in the client properties of the top level container.
64+
if (component instanceof RootPaneContainer) {
65+
component = ((RootPaneContainer) component).getRootPane();
66+
}
67+
if (!(component instanceof JComponent)) {
68+
return null;
69+
}
70+
JComponent jComp = ((JComponent) component);
71+
SwingEventService eventService = (SwingEventService) jComp.getClientProperty(CLIENT_PROPERTY_KEY_TOP_LEVEL_EVENT_SERVICE);
72+
if (eventService == null) {
73+
eventService = new SwingEventService();
74+
jComp.putClientProperty(CLIENT_PROPERTY_KEY_TOP_LEVEL_EVENT_SERVICE, eventService);
75+
}
76+
return eventService;
77+
} else {
78+
component = component.getParent();
79+
}
80+
}
81+
}
82+
return null;
83+
}
84+
}

0 commit comments

Comments
 (0)