Repository: peholmst/vaadin4spring
Branch: master
Commit: 8184d775454c
Files: 32
Total size: 120.0 KB
Directory structure:
gitextract_rbhuxx4x/
├── .gitignore
├── LICENSE.txt
├── README.md
├── eventbus/
│ ├── README.md
│ ├── pom.xml
│ └── src/
│ ├── main/
│ │ └── java/
│ │ └── org/
│ │ └── vaadin/
│ │ └── spring/
│ │ └── events/
│ │ ├── Event.java
│ │ ├── EventBus.java
│ │ ├── EventBusAware.java
│ │ ├── EventBusListener.java
│ │ ├── EventBusListenerMethodFilter.java
│ │ ├── EventScope.java
│ │ ├── ExactTopicFilter.java
│ │ ├── HierachyTopicFilter.java
│ │ ├── NoEventBusListenerMethodFilter.java
│ │ ├── TopicFilter.java
│ │ ├── annotation/
│ │ │ ├── EnableEventBus.java
│ │ │ ├── EventBusListenerMethod.java
│ │ │ ├── EventBusListenerTopic.java
│ │ │ └── EventBusProxy.java
│ │ ├── config/
│ │ │ └── EventBusConfiguration.java
│ │ ├── internal/
│ │ │ ├── AbstractListenerWrapper.java
│ │ │ ├── ClassUtils.java
│ │ │ ├── EventBusListenerWrapper.java
│ │ │ ├── ListenerCollection.java
│ │ │ ├── MethodListenerWrapper.java
│ │ │ └── ScopedEventBus.java
│ │ └── support/
│ │ ├── ApplicationContextEventBroker.java
│ │ └── VaadinEventBusAwareProcessor.java
│ └── test/
│ └── java/
│ └── org/
│ └── vaadin/
│ └── spring/
│ └── events/
│ ├── integration/
│ │ └── ScopedEventBusIntegrationTest.java
│ ├── internal/
│ │ └── ScopedEventBusTest.java
│ └── support/
│ └── ApplicationContextEventBrokerTest.java
└── pom.xml
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.orig
# Maven
target/
*.releaseBackup
release.properties
# IntelliJ
*.iml
.idea/
# Eclipse
.settings/
*.project
*.classpath
*.springBeans
# Vaadin
samples/*-sample*/src/main/webapp/VAADIN/themes/*.css
samples/*-sample*/src/main/webapp/VAADIN/themes/**/*.css
samples/*-sample*/src/main/webapp/VAADIN/widgetsets/
samples/*-sample*/src/main/resources/VAADIN/widgetsets/
samples/*-sample*/src/main/resources/VAADIN/themes/**/*.css
# JRebel
rebel.xml
================================================
FILE: LICENSE.txt
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
Vaadin4Spring
=============
This project started as a prototype of an official Vaadin Spring add-on, back in the day when Vaadin 8 was new.
That was many years ago and a lot has happened since that time. Now we have Vaadin 14 and I have deleted almost all
of the extensions and addons since it did not make sense to port them to Vaadin 14.
All that remains is the event bus that is kept by popular demand. **Please note, however, that the event bus has a
design flaw that can lead to potentially serious security problems if used in the wrong way.** Check the
[README](eventbus/README.md) for more information.
================================================
FILE: eventbus/README.md
================================================
The Vaadin4Spring Event Bus
===========================
**Do not use this event bus in new projects.** This version is published to make it easier to port existing
applications that use Vaadin4Spring from Vaadin 8 to Vaadin 14.
## Security Issue with the Application Scoped Event Bus
You can run into serious security problems with the application scoped event bus if you are not careful. Events are
dispatched synchronously to all listeners in the thread that originally fired the event. This means that **all
event listeners will run within the security context of the user that fired the event**.
Because of this I seriously discourage developers from using the application scoped event bus in their projects.
I can't fix this issue either since that would break existing software that relies on the events being dispatched
in this way.
There are discussions of creating a completely new event bus for Vaadin 14+ that would not have this design flaw.
================================================
FILE: eventbus/pom.xml
================================================
4.0.0org.vaadin.springparent-pom14.0.1-SNAPSHOT../org.vaadin.spring.addonsvaadin-spring-addon-eventbusjarVaadin4Spring Event Buscom.vaadinvaadin-springorg.mockitomockito-coretestorg.junit.jupiterjunit-jupiter-enginetestorg.springframeworkspring-testtestcom.vaadinvaadin-spring-boot-startertest
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/Event.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events;
import java.io.Serializable;
/**
* A class that represents an event that has been published on an {@link org.vaadin.spring.events.EventBus}.
*
* @author Petter Holmström (petter@vaadin.com)
* @see EventBus#publish(Object, Object)
*/
public class Event implements Serializable {
private static final long serialVersionUID = 4818820872533486223L;
private final EventBus eventBus;
private final Object source;
private final String topic;
private final long timestamp;
private final T payload;
public Event(EventBus eventBus, Object source, T payload) {
this(eventBus, source, payload, "");
}
public Event(EventBus eventBus, Object source, T payload, String topic) {
this.eventBus = eventBus;
this.source = source;
this.payload = payload;
this.topic = topic != null ? topic : "";
this.timestamp = System.currentTimeMillis();
}
/**
* Gets the event bus on which the event was originally published.
*
* @return the event bus, never {@code null}.
*/
public EventBus getEventBus() {
return eventBus;
}
/**
* Gets the scope of the event.
*
* @return the scope, never {@code null}.
*/
public EventScope getScope() {
return eventBus.getScope();
}
/**
* Gets the object that published the event on the event bus.
*
* @return the source of the event, never {@code null}.
*/
public Object getSource() {
return source;
}
/**
* Gets the string which specifies the topic of the event on the event bus.
*
* @return the topic of the event, never {@code null}.
*/
public String getTopic() {
return topic;
}
/**
* Gets the timestamp when the event was published on the event bus.
*
* @return the timestamp.
*/
public long getTimestamp() {
return timestamp;
}
/**
* Gets the payload of the event.
*
* @return the payload, never {@code null}.
*/
public T getPayload() {
return payload;
}
@Override
public String toString() {
return String.format("%s[scope=%s, eventBus=%s, ts=%d, source=[%s], payload=[%s]]",
getClass().getSimpleName(), getScope(), getEventBus(), getTimestamp(), getSource(), getPayload());
}
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/EventBus.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events;
/**
* Interface defining an event bus. This event bus infrastructure complements the
* {@link org.springframework.context.ApplicationEventPublisher} in the following ways:
*
*
Events propagate from parent buses to children
*
Events are scoped
*
*
* There are three event scopes, and therefore three event bus types (each with their own sub interface):
*
*
{@link EventScope#APPLICATION} events are published to the entire application.
*
{@link EventScope#SESSION} events are published to the current session.
*
{@link EventScope#UI} events are published to the current UI.
*
*
* The event buses are chained in the following way:
*
*
Application events are propagated to the session event bus.
*
Session events are propagated to the UI event bus.
*
* Furthermore, {@link org.springframework.context.ApplicationEventPublisher} events can be propagated to any event bus
* by using {@link org.vaadin.spring.events.support.ApplicationContextEventBroker}.
*
* You select which {@code EventBus} implementation to inject by using the corresponding interface. For example, to
* inject the UI-scoped event bus, you would use:
*
* @Autowired UIEventBus myUIScopedEventBus;
*
* With this implementation, you can subscribe to and publish events of the application, session and UI scopes (see
* {@link #publish(EventScope, Object, Object)}).
*
* @author Petter Holmström (petter@vaadin.com)
*/
public interface EventBus {
/**
* Publishes the specified payload on the event bus, using the scope of this particular event bus.
*
* @param sender the object that published the event, never {@code null}.
* @param payload the payload of the event to publish, never {@code null}.
* @param the type of the payload.
* @see #getScope()
*/
void publish(Object sender, T payload);
/**
* Publishes the specified payload on the event bus, using the scope of this particular event bus.
* The topic specifies which listeners will be notified.
*
* @param topic the topic of the event to publish, never {@code null}.
* @param sender the object that published the event, never {@code null}.
* @param payload the payload of the event to publish, never {@code null}.
* @param the type of the payload.
* @see #getScope()
*/
void publish(String topic, Object sender, T payload);
/**
* Publishes the specified payload on the event bus, or any of its parent buses, depending on the event scope.
*
* @param scope the scope of the event, never {@code null}.
* @param sender the object that published the event, never {@code null}.
* @param payload the payload of the event to publish, never {@code null}.
* @param the type of the payload;
* @throws UnsupportedOperationException if the payload could not be published with the specified scope.
* @see #publish(Object, Object)
*/
void publish(EventScope scope, Object sender, T payload) throws UnsupportedOperationException;
/**
* Publishes the specified payload on the event bus, or any of its parent buses, depending on the event scope.
* The topic specifies which listeners will be notified.
*
* @param scope the scope of the event, never {@code null}.
* @param topic the topic of the event to publish, never {@code null}.
* @param sender the object that published the event, never {@code null}.
* @param payload the payload of the event to publish, never {@code null}.
* @param the type of the payload;
* @throws UnsupportedOperationException if the payload could not be published with the specified scope.
* @see #publish(Object, Object)
*/
void publish(EventScope scope, String topic, Object sender, T payload) throws UnsupportedOperationException;
/**
* Gets the scope of the events published on this event bus.
*
* @return the event scope, never {@code null}.
* @see org.vaadin.spring.events.Event#getScope()
*/
EventScope getScope();
/**
* Subscribes the specified listener to the event bus, including propagated events from parent event buses.
* The event bus will analyse the payload type of the listener to determine which events it is interested in
* receiving.
* This is the same as calling {@link #subscribe(EventBusListener, boolean) subscribe(listener, true)}.
*
* @param listener the listener to subscribe, never {@code null}.
* @param the type of payload the listener is interested in.
* @see #unsubscribe(EventBusListener)
* @see #subscribeWithWeakReference(EventBusListener)
*/
void subscribe(EventBusListener listener);
/**
* Same as {@link #subscribe(EventBusListener)}, but uses a weak reference to store the listener internally.
*/
void subscribeWithWeakReference(EventBusListener listener);
/**
* Subscribes the topic interested listener to the event bus, including propagated events from parent event buses.
* The event bus will analyse the payload type and topic of the listener to determine which events it is interested
* in receiving.
* @param listener the listener to subscribe, never {@code null}
* @param topic the topic of listener interest
*
* @param the type of payload the listener is interested in
*/
void subscribe(EventBusListener listener, String topic);
/**
* Same as {@link #subscribe(EventBusListener, String)}, but uses a weak reference to store the listener
* internally.
*/
void subscribeWithWeakReference(EventBusListener listener, String topic);
/**
* Subscribes the specified listener to the event bus. The event bus will analyse the
* payload type of the listener to determine which events it is interested in receiving.
*
* @param listener the listener to subscribe, never {@code null}.
* @param includingPropagatingEvents true to notify the listener of events that have propagated from the chain of
* parent event buses, false to only notify the listeners of events that are directly published on this event
* bus.
* @param the type of payload the listener is interested in.
* @see #unsubscribe(EventBusListener)
* @see #subscribeWithWeakReference(EventBusListener, boolean)
*/
void subscribe(EventBusListener listener, boolean includingPropagatingEvents);
/**
* Same as {@link #subscribe(EventBusListener, boolean)}, but uses a weak reference to store the listener
* internally.
*/
void subscribeWithWeakReference(EventBusListener listener, boolean includingPropagatingEvents);
/**
* Subscribes the specified listener to the event bus. The listener need not implement the
* {@link org.vaadin.spring.events.EventBusListener} interface,
* but must contain one or more methods that are annotated with the
* {@link org.vaadin.spring.events.annotation.EventBusListenerMethod} interface and conform to one of these method
* signatures: myMethodName(Event<MyPayloadType>) or myMethodName(MyPayloadType).
* The event bus will analyse the payload type of the listener methods to determine
* which events the different methods are interested in receiving. This is the same as calling
* {@link #subscribe(Object, boolean) subscribe(listener, true)}.
*
* @param listener the listener to subscribe, never {@code null}.
* @see #subscribeWithWeakReference(Object)
*/
void subscribe(Object listener);
/**
* Same as {@link #subscribe(Object)}, but uses a weak reference to store the listener internally.
*/
void subscribeWithWeakReference(Object listener);
/**
* Subscribes the topic interested listener to the event bus. The listener need not implement the
* {@link org.vaadin.spring.events.EventBusListener} interface,
* but must contain one or more methods that are annotated with the
* {@link org.vaadin.spring.events.annotation.EventBusListenerMethod} interface and conform to one of these method
* signatures: myMethodName(Event<MyPayloadType>) or myMethodName(MyPayloadType).
* The event bus will analyse the payload type of the listener methods to determine
* which events the different methods are interested in receiving.
*
* Example:
* subscribe(Listener.this, "/news");
* @param listener the listener to subscribe, never {@code null}.
* @param topic the topic of listener interest
* @see #subscribeWithWeakReference(Object, String)
*/
void subscribe(Object listener, String topic);
/**
* Same as {@link #subscribe(Object, String)}, but uses a weak reference to store the listener internally.
*/
void subscribeWithWeakReference(Object listener, String topic);
/**
* Subscribes the specified listener to the event bus. The listener need not implement the
* {@link org.vaadin.spring.events.EventBusListener} interface,
* but must contain one or more methods that are annotated with the
* {@link org.vaadin.spring.events.annotation.EventBusListenerMethod} interface and conform to one of these method
* signatures: myMethodName(Event<MyPayloadType>) or myMethodName(MyPayloadType).
* The event bus will analyse the payload type of the listener methods to determine
* which events the different methods are interested in receiving.
*
* @param listener the listener to subscribe, never {@code null}.
* @param includingPropagatingEvents true to notify the listener of events that have propagated from the chain of
* parent event buses, false to only notify the listeners of events that are directly published on this event
* bus.
* @see #unsubscribe(Object)
* @see #subscribeWithWeakReference(Object, boolean)
*/
void subscribe(Object listener, boolean includingPropagatingEvents);
/**
* Same as {@link #subscribe(Object, boolean)}, but uses a weak reference to store the listener internally.
*/
void subscribeWithWeakReference(Object listener, boolean includingPropagatingEvents);
/**
* Unsubscribes the specified listener from the event bus. Also works for listeners stored with weak references.
*
* @param listener the listener to unsubscribe, never {@code null}.
* @param the type of the payload.
* @see #subscribe(EventBusListener)
* @see #subscribe(EventBusListener, boolean)
*/
void unsubscribe(EventBusListener listener);
/**
* Unsubscribes the specified listener (and all its listener methods) from the event bus. Also works for listeners
* stored with weak references.
*
* @param listener the listener to unsubscribe, never {@code null}.
* @see #subscribe(Object)
* @see #subscribe(Object, boolean)
*/
void unsubscribe(Object listener);
/**
* Interface implemented by the application scoped event bus.
*
* @see org.vaadin.spring.events.EventScope#APPLICATION
*/
interface ApplicationEventBus extends EventBus {
}
/**
* Interface implemented by the session scoped event bus.
*
* @see org.vaadin.spring.events.EventScope#SESSION
*/
interface SessionEventBus extends EventBus {
}
/**
* Interface implemented by the UI scoped event bus.
*
* @see org.vaadin.spring.events.EventScope#UI
*/
interface UIEventBus extends EventBus {
}
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/EventBusAware.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events;
import org.springframework.beans.factory.Aware;
/**
* Marker super interface for beans that want to get notified of a specific type of event bus.
*
* @author Petter Holmström (petter@vaadin.com)
*/
public interface EventBusAware extends Aware {
/**
* Interface to be implemented by beans that want to get notified of the
* application event bus.
*/
interface ApplicationEventBusAware extends EventBusAware {
/**
* Sets the application scoped event bus.
*/
void setApplicationEventBus(EventBus.ApplicationEventBus applicationEventBus);
}
/**
* Interface to be implemented by beans that want to get notified of the
* session event bus.
*/
interface SessionEventBusAware extends EventBusAware {
/**
* Sets the session scoped event bus.
*/
void setSessionEventBus(EventBus.SessionEventBus sessionEventBus);
}
/**
* Interface to be implemented by beans that want to get notified of the
* UI event bus.
*/
interface UIEventBusAware extends EventBusAware {
/**
* Sets the UI scoped event bus.
*/
void setUIEventBus(EventBus.UIEventBus uiEventBus);
}
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/EventBusListener.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events;
import java.io.Serializable;
/**
* Interface to be implemented by listeners that want to subscribe to an {@link org.vaadin.spring.events.EventBus}.
*
* @param type of event payloads that the listener is interested in receiving.
* @author Petter Holmström (petter@vaadin.com)
*/
public interface EventBusListener extends Serializable {
/**
* Called when an event has been received.
*
* @param event the event, never {@code null}.
*/
void onEvent(Event event);
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/EventBusListenerMethodFilter.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events;
/**
*
* A method annotated with @EventBusListenerMethod will be invoked if it is
* subscribed to the EventBus that published the Event
* (or Object payload). That method will oftentimes employ filtering code
* in the method internals, because of the possibility that multiple annotated methods
* might listen to same the Event.
*
*
* As a convenience, an implementation of this filter may be defined in
* {@link org.vaadin.spring.events.annotation.EventBusListenerMethod#filter()}
* and stand in place of such filtering code.
*
* @author Chris Phillipson (fastnsilver@gmail.com)
*
*/
public interface EventBusListenerMethodFilter {
/**
* Criteria used to influence when an @EventBusListenerMethod
* annotated method with this filter defined will execute
* @param event EventBus event
* @return true if filtering condition met; false otherwise
*/
boolean filter(Event> event);
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/EventScope.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events;
/**
* Enumeration of event scopes.
*
* @author Petter Holmström (petter@vaadin.com)
*/
public enum EventScope {
/**
* The event is application wide.
*/
APPLICATION,
/**
* The event is specific to the current (Vaadin) session.
*/
SESSION,
/**
* The event is specific to the current UI.
*/
UI,
/**
* Undefined event scope. An internal event scope used only when no scope has been explicitly defined.
*
* @see org.vaadin.spring.events.annotation.EventBusListenerMethod#scope()
*/
UNDEFINED
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/ExactTopicFilter.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events;
/**
* An implementation of {@link org.vaadin.spring.events.TopicFilter}
* which validates the topics with an exact match (equals).
*
* @author Marco Luthardt (marco.luthardt@iandme.net)
*/
public class ExactTopicFilter implements TopicFilter {
@Override
public boolean validTopic(String eventTopic, String listenerTopic) {
return eventTopic.equals(listenerTopic);
}
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/HierachyTopicFilter.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events;
/**
* An implementation of {@link org.vaadin.spring.events.TopicFilter}
* which validates the topics hierarchical. This means, that the
* listener filter will be checked as prefixed substring against
* the event topic.
*
*
*
match: eventTopic = "foo.bar" and listenerTopic = "foo"
*
no match: eventTopic = "foo" and listenerTopic = "foo.bar"
*
no match: eventTopic = "foo.bar" and listenerTopic = "foo.not"
*
*
* @author Marco Luthardt (marco.luthardt@iandme.net)
*/
public class HierachyTopicFilter implements TopicFilter {
@Override
public boolean validTopic(String eventTopic, String listenerTopic) {
return eventTopic.startsWith(listenerTopic);
}
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/NoEventBusListenerMethodFilter.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events;
/**
* A default filter implementation which always returns true.
* @author Chris Phillipson (fastnsilver@gmail.com)
* @see org.vaadin.spring.events.annotation.EventBusListenerMethod#scope()
*/
public class NoEventBusListenerMethodFilter implements EventBusListenerMethodFilter {
@Override
public boolean filter(Event> event) {
return true;
}
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/TopicFilter.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events;
/**
* The interface defines a method to validate a given event topic
* an listener topic. The event topic is provided when publishing
* an event and the listener topic by the {@link org.vaadin.spring.events.annotation.EventBusListenerTopic}
* annotation. An implementation of this interface can be used as
* parameter of this annotation.
*
* @author Marco Luthardt (marco.luthardt@iandme.net)
* @see org.vaadin.spring.events.annotation.EventBusListenerTopic
*/
public interface TopicFilter {
/**
* Validates the given event topic against the listener topic.
*
* @param eventTopic the topic provided by while publishing an event, never {@code null}
* @param listenerTopic the topic of the listener method, never {@code null}
*
* @return true true if the event topic matches the listener topic, otherwise false
*/
boolean validTopic(String eventTopic, String listenerTopic);
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/annotation/EnableEventBus.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
import org.vaadin.spring.events.config.EventBusConfiguration;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EventBusConfiguration.class)
public @interface EnableEventBus {
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/annotation/EventBusListenerMethod.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventBusListener;
import org.vaadin.spring.events.EventBusListenerMethodFilter;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.NoEventBusListenerMethodFilter;
/**
* Annotation to be placed on event bus listener methods. A listener method must always conform to one of the following method signatures:
*
*
*
* A listener method can have any visibility and any return type.
*
* @author Petter Holmström (petter@vaadin.com)
* @see org.vaadin.spring.events.EventBusListener
* @see EventBus#subscribe(Object)
* @see EventBus#subscribe(Object, boolean)
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EventBusListenerMethod {
/**
* The default scope of a listener method is EventScope.UNDEFINED
* This means that listener will listen for any {@link EventScope} if {@link EventBus#subscribe(EventBusListener, boolean)} is set to propagate event
*/
EventScope scope() default EventScope.UNDEFINED;
Class extends EventBusListenerMethodFilter> filter() default NoEventBusListenerMethodFilter.class;
/**
* Filter by source class
*/
Class>[] source() default {};
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/annotation/EventBusListenerTopic.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.vaadin.spring.events.ExactTopicFilter;
import org.vaadin.spring.events.TopicFilter;
/**
* Annotation to be placed on event bus listener methods, additional to
* the {@link org.vaadin.spring.events.annotation.EventBusListenerMethod} annotation.
* A topic is specified as string which will be defined when publishing an event.
* Each method annotated with this annotation and the corresponding topic will be
* called as listener.
*
* Topics can be filtered with implementations of the {@link org.vaadin.spring.events.TopicFilter} interface.
*
* @author Marco Luthardt (marco.luthardt@iandme.net)
* @see org.vaadin.spring.events.annotation.EventBusListenerMethod
* @see org.vaadin.spring.events.TopicFilter
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EventBusListenerTopic {
/**
* A topic is a string which can be specified while publishing an event. The
* method will only called when the topic matches the given String in the
* published method.
*/
String topic() default "";
/**
* The filter to be used to validate the published and listener topic.
*
* @return an implementation of the {@link org.vaadin.spring.events.TopicFilter} interface.
*/
Class extends TopicFilter> filter() default ExactTopicFilter.class;
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/annotation/EventBusProxy.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events.annotation;
import org.springframework.beans.factory.annotation.Qualifier;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Qualifier to be used to indicate that a proxy of an {@link org.vaadin.spring.events.EventBus} should be injected.
*
* @author Petter Holmström (petter@vaadin.com)
*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Qualifier
public @interface EventBusProxy {
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/config/EventBusConfiguration.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events.config;
import com.vaadin.flow.spring.scopes.VaadinSessionScope;
import com.vaadin.flow.spring.scopes.VaadinUIScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.annotation.EventBusProxy;
import org.vaadin.spring.events.internal.ScopedEventBus;
import org.vaadin.spring.events.support.VaadinEventBusAwareProcessor;
/**
* Configuration class to configure the Spring Vaadin Eventbus
*
* @author Gert-Jan Timmer (gjr.timmer@gmail.com)
*/
@Configuration
public class EventBusConfiguration {
@Bean
VaadinEventBusAwareProcessor vaadinEventBusProcessor() {
return new VaadinEventBusAwareProcessor();
}
@Bean
EventBus.ApplicationEventBus applicationEventBus() {
return new ScopedEventBus.DefaultApplicationEventBus();
}
@Bean
@Scope(value = VaadinSessionScope.VAADIN_SESSION_SCOPE_NAME, proxyMode = ScopedProxyMode.INTERFACES)
@EventBusProxy
EventBus.SessionEventBus proxiedSessionEventBus() {
return sessionEventBus();
}
@Bean
@Scope(value = VaadinSessionScope.VAADIN_SESSION_SCOPE_NAME, proxyMode = ScopedProxyMode.NO)
@Primary
EventBus.SessionEventBus sessionEventBus() {
return new ScopedEventBus.DefaultSessionEventBus(applicationEventBus());
}
@Bean
@Scope(value = VaadinUIScope.VAADIN_UI_SCOPE_NAME, proxyMode = ScopedProxyMode.INTERFACES)
@EventBusProxy
EventBus.UIEventBus proxiedUiEventBus() {
return uiEventBus();
}
@Bean
@Scope(value = VaadinUIScope.VAADIN_UI_SCOPE_NAME, proxyMode = ScopedProxyMode.NO)
@Primary
EventBus.UIEventBus uiEventBus() {
return new ScopedEventBus.DefaultUIEventBus(sessionEventBus());
}
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/internal/AbstractListenerWrapper.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events.internal;
import org.vaadin.spring.events.Event;
import org.vaadin.spring.events.EventBus;
/**
* Base implementation of {@link org.vaadin.spring.events.internal.ListenerCollection.Listener} that implements
* the {@link #supports(org.vaadin.spring.events.Event)} method. An event is supported if:
*
*
The payload type of the listener is either the same type as, or a supertype of, the payload type of the event
*
The listener allows propagating events, or the event was originally published on event bus that the listener was subscribed to
*
*
* @author Petter Holmström (petter@vaadin.com)
*/
abstract class AbstractListenerWrapper implements ListenerCollection.Listener {
private static final long serialVersionUID = 6211420845165980671L;
private final EventBus owningEventBus;
private final Object listenerTarget;
private final boolean includingPropagatingEvents;
private final String topic;
AbstractListenerWrapper(EventBus owningEventBus, Object listenerTarget, String topic, boolean includingPropagatingEvents) {
this.owningEventBus = owningEventBus;
this.topic = topic;
this.listenerTarget = listenerTarget;
this.includingPropagatingEvents = includingPropagatingEvents;
}
/**
* Gets the payload type of the listener.
*/
protected abstract Class> getPayloadType();
/**
* Gets the target object that this listener is wrapping.
*/
public Object getListenerTarget() {
return listenerTarget;
}
@Override
public boolean supports(Event> event) {
final Class> eventPayloadType = event.getPayload().getClass();
return (event.getTopic().equals(topic) || topic == null) &&
getPayloadType().isAssignableFrom(eventPayloadType) &&
(includingPropagatingEvents || event.getEventBus().equals(owningEventBus));
}
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/internal/ClassUtils.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events.internal;
/**
* Utility methods for working with classes and class members.
*
* @author Petter Holmström (petter@vaadin.com)
*/
final class ClassUtils {
private ClassUtils() {
}
/**
* Visitor interface used with {@link ClassUtils#visitClassHierarchy(ClassUtils.ClassVisitor, Class)}.
*/
public interface ClassVisitor {
void visit(Class> clazz);
}
/**
* Visits the entire class hierarchy from {@code subClass} to {@code Object}.
*
* @param visitor the visitor to use, must not be {@code null}.
* @param subClass the class whose hierarchy is to be visited, must not be {@code null}.
*/
static void visitClassHierarchy(ClassVisitor visitor, Class> subClass) {
Class> visitedClass = subClass;
while (visitedClass.getSuperclass() != null) {
visitor.visit(visitedClass);
visitedClass = visitedClass.getSuperclass();
}
}
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/internal/EventBusListenerWrapper.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events.internal;
import org.springframework.core.GenericTypeResolver;
import org.springframework.util.Assert;
import org.vaadin.spring.events.Event;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventBusListener;
/**
* Implementation of {@link org.vaadin.spring.events.internal.AbstractListenerWrapper} that wraps a single
* {@link org.vaadin.spring.events.EventBusListener} instance.
*
* @author Petter Holmström (petter@vaadin.com)
*/
class EventBusListenerWrapper extends AbstractListenerWrapper {
private static final long serialVersionUID = 8964309195124823892L;
private final Class> payloadType;
EventBusListenerWrapper(EventBus owningEventBus, EventBusListener> listenerTarget, String topic, boolean includingPropagatingEvents) {
super(owningEventBus, listenerTarget, topic, includingPropagatingEvents);
payloadType = GenericTypeResolver.resolveTypeArgument(listenerTarget.getClass(), EventBusListener.class);
Assert.notNull(payloadType, "Could not resolve payload type");
}
@Override
@SuppressWarnings("rawtypes")
public EventBusListener getListenerTarget() {
return (EventBusListener) super.getListenerTarget();
}
@Override
protected Class> getPayloadType() {
return payloadType;
}
@Override
@SuppressWarnings("unchecked")
public void publish(Event> event) {
getListenerTarget().onEvent(event);
}
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/internal/ListenerCollection.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events.internal;
import java.io.Serializable;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vaadin.spring.events.Event;
/**
* A collection of listeners. Intended only for internal use by the framework.
*
* @author Petter Holmström (petter@vaadin.com)
*/
class ListenerCollection implements Serializable {
private static final long serialVersionUID = -6237902400879667320L;
private final Logger logger = LoggerFactory.getLogger(getClass());
private final Set listeners = new HashSet();
private final Set weakListeners = Collections.newSetFromMap(new WeakHashMap());
/**
* Interface defining a listener.
*/
public interface Listener extends Serializable {
/**
* Checks if this listener supports the specified event.
*
* @param event the event to check, never {@code null}.
* @return true if the event is supported, false otherwise.
*/
boolean supports(Event> event);
/**
* Publishes the event to the listener.
*
* @param event the event to publish, never {@code null}.
*/
void publish(Event> event);
}
/**
* Interface defining a listener filter.
*/
public interface ListenerFilter {
/**
* Checks if the specified listener passes the filter.
*
* @param listener the listener to check, never {@code null}.
* @return true if the listener passes the filter, false otherwise.
*/
boolean passes(Listener listener);
}
/**
* Adds the specified {@link org.vaadin.spring.events.internal.ListenerCollection.Listener} to the listener
* collection.
*
* @param listener the listener to add, never {@code null}.
* @see #remove(org.vaadin.spring.events.internal.ListenerCollection.Listener)
*/
void add(Listener listener) {
logger.trace("Adding listener [{}]", listener);
synchronized (listeners) {
listeners.add(listener);
}
}
/**
* Adds the specified {@link org.vaadin.spring.events.internal.ListenerCollection.Listener} to the listener
* collection,
* using a weak reference. This means the listener does not need to be removed to be eligible for garbage
* collection.
*
* @param listener the listener to add, never {@code null}.
*/
void addWithWeakReference(Listener listener) {
logger.trace("Adding listener [{}] using a weak reference", listener);
synchronized (weakListeners) {
weakListeners.add(listener);
}
}
/**
* Removes a {@link org.vaadin.spring.events.internal.ListenerCollection.Listener} previously added by
* {@link #add(org.vaadin.spring.events.internal.ListenerCollection.Listener)}.
* If no listener definition is found in the collection, nothing happens.
*
* @param listener the listener to remove, never {@code null}.
* @see #add(org.vaadin.spring.events.internal.ListenerCollection.Listener)
*/
void remove(Listener listener) {
logger.trace("Removing listener [{}]", listener);
synchronized (listeners) {
listeners.remove(listener);
}
synchronized (weakListeners) {
weakListeners.remove(listener);
}
}
/**
* Removes all {@link org.vaadin.spring.events.internal.ListenerCollection.Listener}s that pass the specified filter
* and that were previously added by
* {@link #add(org.vaadin.spring.events.internal.ListenerCollection.Listener)}.
*
* @param filter the filter that specifies which listeners to remove, never {@code null}.
*/
void removeAll(ListenerFilter filter) {
synchronized (listeners) {
removeFilteredListenersFromSet(filter, listeners);
}
synchronized (weakListeners) {
removeFilteredListenersFromSet(filter, weakListeners);
}
}
/**
* Removes all {@link org.vaadin.spring.events.internal.ListenerCollection.Listener}s from the collection.
*/
void clear() {
synchronized (listeners) {
listeners.clear();
}
synchronized (weakListeners) {
weakListeners.clear();
}
}
/**
* Publishes the specified {@code event} to all
* {@link org.vaadin.spring.events.internal.ListenerCollection.Listener}s that support it.
*
* @param event the event to publish, never {@code null}.
* @see org.vaadin.spring.events.internal.ListenerCollection.Listener#publish(org.vaadin.spring.events.Event)
* @see org.vaadin.spring.events.internal.ListenerCollection.Listener#supports(org.vaadin.spring.events.Event)
*/
public void publish(Event> event) {
Set interestedListeners = new HashSet();
synchronized (listeners) {
addSupportedListenersToSet(listeners, interestedListeners, event);
}
synchronized (weakListeners) {
addSupportedListenersToSet(weakListeners, interestedListeners, event);
}
if (interestedListeners.isEmpty()) {
logger.debug("No listeners supported event [{}]", event);
} else {
for (Listener listener : interestedListeners) {
logger.trace("Publishing event [{}] to listener [{}]", event, listener);
listener.publish(event);
}
}
}
private void addSupportedListenersToSet(Set candidateListeners, Set selectedListeners,
Event event) {
for (Listener candidateListener : candidateListeners) {
if (candidateListener.supports(event)) {
logger.trace("Listener [{}] supports event [{}]", candidateListener, event);
selectedListeners.add(candidateListener);
}
}
}
private void removeFilteredListenersFromSet(ListenerFilter filter, Set listenerSet) {
for (Iterator it = listenerSet.iterator(); it.hasNext();) {
Listener listener = it.next();
if (filter.passes(listener)) {
logger.trace("Removing listener [{}]", listener);
it.remove();
}
}
}
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/internal/MethodListenerWrapper.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events.internal;
import org.vaadin.spring.events.*;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import org.vaadin.spring.events.annotation.EventBusListenerTopic;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
/**
* Implementation of {@link org.vaadin.spring.events.internal.AbstractListenerWrapper} that wraps an object
* that contains a method annotated with {@link org.vaadin.spring.events.annotation.EventBusListenerMethod}. If the object
* contains multiple listener methods, multiple instances of this class should be created.
*
* @author Petter Holmström (petter@vaadin.com)
*/
class MethodListenerWrapper extends AbstractListenerWrapper {
private static final long serialVersionUID = -3624543380547361337L;
private final Class> payloadType;
private final boolean payloadMethod;
private transient Method listenerMethod;
private final String topic;
MethodListenerWrapper(EventBus owningEventBus, Object listenerTarget, String topic, boolean includingPropagatingEvents, Method listenerMethod) {
super(owningEventBus, listenerTarget, topic, includingPropagatingEvents);
this.topic = topic;
if (listenerMethod.getParameterTypes()[0] == Event.class) {
ParameterizedType type = (ParameterizedType) listenerMethod.getGenericParameterTypes()[0];
payloadType = (Class>) type.getActualTypeArguments()[0];
payloadMethod = false;
} else {
payloadType = listenerMethod.getParameterTypes()[0];
payloadMethod = true;
}
this.listenerMethod = listenerMethod;
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
// TODO Read listener method info and look up method
}
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
// TODO Write listener method info
}
@Override
public Class> getPayloadType() {
return payloadType;
}
@Override
public void publish(Event> event) {
listenerMethod.setAccessible(true);
try {
if (payloadMethod) {
listenerMethod.invoke(getListenerTarget(), event.getPayload());
} else {
listenerMethod.invoke(getListenerTarget(), event);
}
} catch (IllegalAccessException e) {
throw new RuntimeException("Could not access listener method " + listenerMethod.getName());
} catch (InvocationTargetException e) {
Throwable targetException = e.getTargetException();
if (targetException instanceof RuntimeException) {
throw (RuntimeException) targetException;
} else {
throw new RuntimeException("A checked exception occurred while invoking listener method " + listenerMethod.getName(), targetException);
}
}
}
@Override
public boolean supports(Event> event) {
boolean supports = super.supports(event);
try {
if (listenerMethod.isAnnotationPresent(EventBusListenerMethod.class)) {
supports = supports && isInterestedListenerMethod(event);
}
if (topic != null) {
return supports;
}
if (listenerMethod.isAnnotationPresent(EventBusListenerTopic.class) && supports) {
supports = isInTopic(event);
} else if (!event.getTopic().isEmpty()) {
supports = false;
}
} catch (Exception e) {
throw new RuntimeException("A checked exception occurred while invoking listener method " + listenerMethod.getName(), e);
}
return supports;
}
private boolean isInterestedListenerMethod(Event> event) throws InstantiationException, IllegalAccessException {
EventBusListenerMethod annotation = listenerMethod.getAnnotation(EventBusListenerMethod.class);
EventBusListenerMethodFilter filter = annotation.filter().newInstance();
EventScope scope = annotation.scope();
if (scope.equals(EventScope.UNDEFINED)) {
scope = event.getScope();
}
return filter.filter(event)
&& event.getScope().equals(scope) && isFromSource(event, annotation.source());
}
private boolean isFromSource(Event> event, Class>[] sources) {
if (sources.length == 0) {
return true;
}
boolean result = false;
for (int i = 0; i < sources.length && !result; i++) {
result |= sources[i].isAssignableFrom(event.getSource().getClass());
}
return result;
}
private boolean isInTopic(Event> event) throws InstantiationException, IllegalAccessException {
EventBusListenerTopic annotation = listenerMethod.getAnnotation(EventBusListenerTopic.class);
TopicFilter filter = annotation.filter().newInstance();
return filter.validTopic(event.getTopic(), annotation.topic());
}
}
================================================
FILE: eventbus/src/main/java/org/vaadin/spring/events/internal/ScopedEventBus.java
================================================
/*
* Copyright 2015 The original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.vaadin.spring.events.internal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.support.AopUtils;
import org.vaadin.spring.events.Event;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventBusListener;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import javax.annotation.PreDestroy;
import java.io.Serializable;
import java.lang.reflect.Method;
/**
* Implementation of {@link org.vaadin.spring.events.EventBus} that publishes events with one specific
* {@link org.vaadin.spring.events.EventScope}.
* A scoped event bus can also have a parent event bus, in which case all events published on the parent bus will
* propagate to the scoped event bus as well.
*
* @author Petter Holmström (petter@vaadin.com)
*/
public abstract class ScopedEventBus implements EventBus, Serializable {
private static final long serialVersionUID = -582697574672947883L;
private final Logger logger = LoggerFactory.getLogger(getClass());
private final EventScope eventScope;
private final ListenerCollection listeners = new ListenerCollection();
private EventBus parentEventBus;
private EventBusListener