[
  {
    "path": ".gitignore",
    "content": "*.orig\n\n# Maven\ntarget/\n*.releaseBackup\nrelease.properties\n\n# IntelliJ\n*.iml\n.idea/\n\n# Eclipse\n.settings/\n*.project\n*.classpath\n*.springBeans\n\n# Vaadin\nsamples/*-sample*/src/main/webapp/VAADIN/themes/*.css\nsamples/*-sample*/src/main/webapp/VAADIN/themes/**/*.css\nsamples/*-sample*/src/main/webapp/VAADIN/widgetsets/\nsamples/*-sample*/src/main/resources/VAADIN/widgetsets/\nsamples/*-sample*/src/main/resources/VAADIN/themes/**/*.css\n\n# JRebel\nrebel.xml\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "Vaadin4Spring\n=============\n\nThis project started as a prototype of an official Vaadin Spring add-on, back in the day when Vaadin 8 was new.\nThat was many years ago and a lot has happened since that time. Now we have Vaadin 14 and I have deleted almost all\nof the extensions and addons since it did not make sense to port them to Vaadin 14.\n \nAll that remains is the event bus that is kept by popular demand. **Please note, however, that the event bus has a\ndesign flaw that can lead to potentially serious security problems if used in the wrong way.** Check the \n[README](eventbus/README.md) for more information."
  },
  {
    "path": "eventbus/README.md",
    "content": "The Vaadin4Spring Event Bus\n===========================\n\n**Do not use this event bus in new projects.** This version is published to make it easier to port existing\napplications that use Vaadin4Spring from Vaadin 8 to Vaadin 14.\n\n## Security Issue with the Application Scoped Event Bus\n\nYou can run into serious security problems with the application scoped event bus if you are not careful. Events are\ndispatched synchronously to all listeners in the thread that originally fired the event. This means that **all\nevent listeners will run within the security context of the user that fired the event**. \n\nBecause of this I seriously discourage developers from using the application scoped event bus in their projects.\nI can't fix this issue either since that would break existing software that relies on the events being dispatched\nin this way. \n\nThere are discussions of creating a completely new event bus for Vaadin 14+ that would not have this design flaw.\n "
  },
  {
    "path": "eventbus/pom.xml",
    "content": "<?xml version=\"1.0\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <parent>\n        <groupId>org.vaadin.spring</groupId>\n        <artifactId>parent-pom</artifactId>\n        <version>14.0.1-SNAPSHOT</version>\n        <relativePath>../</relativePath>\n    </parent>\n\n    <groupId>org.vaadin.spring.addons</groupId>\n    <artifactId>vaadin-spring-addon-eventbus</artifactId>\n    <packaging>jar</packaging>\n\n    <name>Vaadin4Spring Event Bus</name>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.vaadin</groupId>\n            <artifactId>vaadin-spring</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-core</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.junit.jupiter</groupId>\n            <artifactId>junit-jupiter-engine</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>com.vaadin</groupId>\n            <artifactId>vaadin-spring-boot-starter</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n</project>\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/Event.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events;\n\nimport java.io.Serializable;\n\n/**\n * A class that represents an event that has been published on an {@link org.vaadin.spring.events.EventBus}.\n *\n * @author Petter Holmström (petter@vaadin.com)\n * @see EventBus#publish(Object, Object)\n */\npublic class Event<T> implements Serializable {\n\n    private static final long serialVersionUID = 4818820872533486223L;\n\n    private final EventBus eventBus;\n\n    private final Object source;\n\n    private final String topic;\n    \n    private final long timestamp;\n\n    private final T payload;\n\n    public Event(EventBus eventBus, Object source, T payload) {\n    \tthis(eventBus, source, payload, \"\");\n    }\n\n    public Event(EventBus eventBus, Object source, T payload, String topic) {\n        this.eventBus = eventBus;\n        this.source = source;\n        this.payload = payload;\n        this.topic = topic != null ? topic : \"\";\n        this.timestamp = System.currentTimeMillis();\n    }\n\n    /**\n     * Gets the event bus on which the event was originally published.\n     *\n     * @return the event bus, never {@code null}.\n     */\n    public EventBus getEventBus() {\n        return eventBus;\n    }\n\n    /**\n     * Gets the scope of the event.\n     *\n     * @return the scope, never {@code null}.\n     */\n    public EventScope getScope() {\n        return eventBus.getScope();\n    }\n\n    /**\n     * Gets the object that published the event on the event bus.\n     *\n     * @return the source of the event, never {@code null}.\n     */\n    public Object getSource() {\n        return source;\n    }\n\n    /**\n     * Gets the string which specifies the topic of the event on the event bus.\n     * \n     * @return the topic of the event, never {@code null}.\n     */\n    public String getTopic() {\n\t\treturn topic;\n\t}\n    \n    /**\n     * Gets the timestamp when the event was published on the event bus.\n     *\n     * @return the timestamp.\n     */\n    public long getTimestamp() {\n        return timestamp;\n    }\n\n    /**\n     * Gets the payload of the event.\n     *\n     * @return the payload, never {@code null}.\n     */\n    public T getPayload() {\n        return payload;\n    }\n\n    @Override\n    public String toString() {\n        return String.format(\"%s[scope=%s, eventBus=%s, ts=%d, source=[%s], payload=[%s]]\",\n                getClass().getSimpleName(), getScope(), getEventBus(), getTimestamp(), getSource(), getPayload());\n    }\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/EventBus.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events;\n\n/**\n * Interface defining an event bus. This event bus infrastructure complements the\n * {@link org.springframework.context.ApplicationEventPublisher} in the following ways:\n * <ul>\n * <li>Events propagate from parent buses to children</li>\n * <li>Events are scoped</li>\n * </ul>\n * <p>\n * There are three event scopes, and therefore three event bus types (each with their own sub interface):\n * <ol>\n * <li>{@link EventScope#APPLICATION} events are published to the entire application.</li>\n * <li>{@link EventScope#SESSION} events are published to the current session.</li>\n * <li>{@link EventScope#UI} events are published to the current UI.</li>\n * </ol>\n * <p>\n * The event buses are chained in the following way:\n * <ul>\n * <li>Application events are propagated to the session event bus.</li>\n * <li>Session events are propagated to the UI event bus.</li>\n * </ul>\n * Furthermore, {@link org.springframework.context.ApplicationEventPublisher} events can be propagated to any event bus\n * by using {@link org.vaadin.spring.events.support.ApplicationContextEventBroker}.\n * <p>\n * You select which {@code EventBus} implementation to inject by using the corresponding interface. For example, to\n * inject the UI-scoped event bus, you would use:\n * <code>\n * &#64;Autowired UIEventBus myUIScopedEventBus;\n * </code>\n * With this implementation, you can subscribe to and publish events of the application, session and UI scopes (see\n * {@link #publish(EventScope, Object, Object)}).\n *\n * @author Petter Holmström (petter@vaadin.com)\n */\npublic interface EventBus {\n\n    /**\n     * Publishes the specified payload on the event bus, using the scope of this particular event bus.\n     *\n     * @param sender the object that published the event, never {@code null}.\n     * @param payload the payload of the event to publish, never {@code null}.\n     * @param <T> the type of the payload.\n     * @see #getScope()\n     */\n    <T> void publish(Object sender, T payload);\n\n    /**\n     * Publishes the specified payload on the event bus, using the scope of this particular event bus.\n     * The topic specifies which listeners will be notified.\n     *\n     * @param topic the topic of the event to publish, never {@code null}.\n     * @param sender the object that published the event, never {@code null}.\n     * @param payload the payload of the event to publish, never {@code null}.\n     * @param <T> the type of the payload.\n     * @see #getScope()\n     */\n    <T> void publish(String topic, Object sender, T payload);\n\n    /**\n     * Publishes the specified payload on the event bus, or any of its parent buses, depending on the event scope.\n     *\n     * @param scope the scope of the event, never {@code null}.\n     * @param sender the object that published the event, never {@code null}.\n     * @param payload the payload of the event to publish, never {@code null}.\n     * @param <T> the type of the payload;\n     * @throws UnsupportedOperationException if the payload could not be published with the specified scope.\n     * @see #publish(Object, Object)\n     */\n    <T> void publish(EventScope scope, Object sender, T payload) throws UnsupportedOperationException;\n\n    /**\n     * Publishes the specified payload on the event bus, or any of its parent buses, depending on the event scope.\n     * The topic specifies which listeners will be notified.\n     *\n     * @param scope the scope of the event, never {@code null}.\n     * @param topic the topic of the event to publish, never {@code null}.\n     * @param sender the object that published the event, never {@code null}.\n     * @param payload the payload of the event to publish, never {@code null}.\n     * @param <T> the type of the payload;\n     * @throws UnsupportedOperationException if the payload could not be published with the specified scope.\n     * @see #publish(Object, Object)\n     */\n    <T> void publish(EventScope scope, String topic, Object sender, T payload) throws UnsupportedOperationException;\n\n    /**\n     * Gets the scope of the events published on this event bus.\n     *\n     * @return the event scope, never {@code null}.\n     * @see org.vaadin.spring.events.Event#getScope()\n     */\n    EventScope getScope();\n\n    /**\n     * Subscribes the specified listener to the event bus, including propagated events from parent event buses.\n     * The event bus will analyse the payload type of the listener to determine which events it is interested in\n     * receiving.\n     * This is the same as calling {@link #subscribe(EventBusListener, boolean) subscribe(listener, true)}.\n     *\n     * @param listener the listener to subscribe, never {@code null}.\n     * @param <T> the type of payload the listener is interested in.\n     * @see #unsubscribe(EventBusListener)\n     * @see #subscribeWithWeakReference(EventBusListener)\n     */\n    <T> void subscribe(EventBusListener<T> listener);\n\n    /**\n     * Same as {@link #subscribe(EventBusListener)}, but uses a weak reference to store the listener internally.\n     */\n    <T> void subscribeWithWeakReference(EventBusListener<T> listener);\n\n    /**\n     * Subscribes the topic interested listener to the event bus, including propagated events from parent event buses.\n     * The event bus will analyse the payload type and topic of the listener to determine which events it is interested\n     * in receiving.\n     * @param listener the listener to subscribe, never {@code null}\n     * @param topic the topic of listener interest\n     *\n     * @param <T> the type of payload the listener is interested in\n     */\n    <T> void subscribe(EventBusListener<T> listener, String topic);\n\n    /**\n     * Same as {@link #subscribe(EventBusListener, String)}, but uses a weak reference to store the listener\n     * internally.\n     */\n    <T> void subscribeWithWeakReference(EventBusListener<T> listener, String topic);\n\n    /**\n     * Subscribes the specified listener to the event bus. The event bus will analyse the\n     * payload type of the listener to determine which events it is interested in receiving.\n     *\n     * @param listener the listener to subscribe, never {@code null}.\n     * @param includingPropagatingEvents true to notify the listener of events that have propagated from the chain of\n     *        parent event buses, false to only notify the listeners of events that are directly published on this event\n     *        bus.\n     * @param <T> the type of payload the listener is interested in.\n     * @see #unsubscribe(EventBusListener)\n     * @see #subscribeWithWeakReference(EventBusListener, boolean)\n     */\n    <T> void subscribe(EventBusListener<T> listener, boolean includingPropagatingEvents);\n\n    /**\n     * Same as {@link #subscribe(EventBusListener, boolean)}, but uses a weak reference to store the listener\n     * internally.\n     */\n    <T> void subscribeWithWeakReference(EventBusListener<T> listener, boolean includingPropagatingEvents);\n\n    /**\n     * Subscribes the specified listener to the event bus. The listener need not implement the\n     * {@link org.vaadin.spring.events.EventBusListener} interface,\n     * but must contain one or more methods that are annotated with the\n     * {@link org.vaadin.spring.events.annotation.EventBusListenerMethod} interface and conform to one of these method\n     * signatures: <code>myMethodName(Event&lt;MyPayloadType&gt;)</code> or <code>myMethodName(MyPayloadType)</code>.\n     * The event bus will analyse the payload type of the listener methods to determine\n     * which events the different methods are interested in receiving. This is the same as calling\n     * {@link #subscribe(Object, boolean) subscribe(listener, true)}.\n     *\n     * @param listener the listener to subscribe, never {@code null}.\n     * @see #subscribeWithWeakReference(Object)\n     */\n    void subscribe(Object listener);\n\n    /**\n     * Same as {@link #subscribe(Object)}, but uses a weak reference to store the listener internally.\n     */\n    void subscribeWithWeakReference(Object listener);\n\n    /**\n     * Subscribes the topic interested listener to the event bus. The listener need not implement the\n     * {@link org.vaadin.spring.events.EventBusListener} interface,\n     * but must contain one or more methods that are annotated with the\n     * {@link org.vaadin.spring.events.annotation.EventBusListenerMethod} interface and conform to one of these method\n     * signatures: <code>myMethodName(Event&lt;MyPayloadType&gt;)</code> or <code>myMethodName(MyPayloadType)</code>.\n     * The event bus will analyse the payload type of the listener methods to determine\n     * which events the different methods are interested in receiving.\n     * <p>\n     * Example:\n     * <code>subscribe(Listener.this, \"/news\");</code>\n     * @param listener the listener to subscribe, never {@code null}.\n     * @param topic the topic of listener interest\n     * @see #subscribeWithWeakReference(Object, String)\n     */\n    void subscribe(Object listener, String topic);\n\n    /**\n     * Same as {@link #subscribe(Object, String)}, but uses a weak reference to store the listener internally.\n     */\n    void subscribeWithWeakReference(Object listener, String topic);\n\n    /**\n     * Subscribes the specified listener to the event bus. The listener need not implement the\n     * {@link org.vaadin.spring.events.EventBusListener} interface,\n     * but must contain one or more methods that are annotated with the\n     * {@link org.vaadin.spring.events.annotation.EventBusListenerMethod} interface and conform to one of these method\n     * signatures: <code>myMethodName(Event&lt;MyPayloadType&gt;)</code> or <code>myMethodName(MyPayloadType)</code>.\n     * The event bus will analyse the payload type of the listener methods to determine\n     * which events the different methods are interested in receiving.\n     *\n     * @param listener the listener to subscribe, never {@code null}.\n     * @param includingPropagatingEvents true to notify the listener of events that have propagated from the chain of\n     *        parent event buses, false to only notify the listeners of events that are directly published on this event\n     *        bus.\n     * @see #unsubscribe(Object)\n     * @see #subscribeWithWeakReference(Object, boolean)\n     */\n    void subscribe(Object listener, boolean includingPropagatingEvents);\n\n    /**\n     * Same as {@link #subscribe(Object, boolean)}, but uses a weak reference to store the listener internally.\n     */\n    void subscribeWithWeakReference(Object listener, boolean includingPropagatingEvents);\n\n    /**\n     * Unsubscribes the specified listener from the event bus. Also works for listeners stored with weak references.\n     *\n     * @param listener the listener to unsubscribe, never {@code null}.\n     * @param <T> the type of the payload.\n     * @see #subscribe(EventBusListener)\n     * @see #subscribe(EventBusListener, boolean)\n     */\n    <T> void unsubscribe(EventBusListener<T> listener);\n\n    /**\n     * Unsubscribes the specified listener (and all its listener methods) from the event bus. Also works for listeners\n     * stored with weak references.\n     *\n     * @param listener the listener to unsubscribe, never {@code null}.\n     * @see #subscribe(Object)\n     * @see #subscribe(Object, boolean)\n     */\n    void unsubscribe(Object listener);\n\n    /**\n     * Interface implemented by the application scoped event bus.\n     *\n     * @see org.vaadin.spring.events.EventScope#APPLICATION\n     */\n    interface ApplicationEventBus extends EventBus {\n    }\n\n    /**\n     * Interface implemented by the session scoped event bus.\n     *\n     * @see org.vaadin.spring.events.EventScope#SESSION\n     */\n    interface SessionEventBus extends EventBus {\n    }\n\n    /**\n     * Interface implemented by the UI scoped event bus.\n     *\n     * @see org.vaadin.spring.events.EventScope#UI\n     */\n    interface UIEventBus extends EventBus {\n    }\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/EventBusAware.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events;\n\nimport org.springframework.beans.factory.Aware;\n\n/**\n * Marker super interface for beans that want to get notified of a specific type of event bus.\n *\n * @author Petter Holmström (petter@vaadin.com)\n */\npublic interface EventBusAware extends Aware {\n\n    /**\n     * Interface to be implemented by beans that want to get notified of the\n     * application event bus.\n     */\n    interface ApplicationEventBusAware extends EventBusAware {\n        /**\n         * Sets the application scoped event bus.\n         */\n        void setApplicationEventBus(EventBus.ApplicationEventBus applicationEventBus);\n    }\n\n    /**\n     * Interface to be implemented by beans that want to get notified of the\n     * session event bus.\n     */\n    interface SessionEventBusAware extends EventBusAware {\n        /**\n         * Sets the session scoped event bus.\n         */\n        void setSessionEventBus(EventBus.SessionEventBus sessionEventBus);\n    }\n\n    /**\n     * Interface to be implemented by beans that want to get notified of the\n     * UI event bus.\n     */\n    interface UIEventBusAware extends EventBusAware {\n        /**\n         * Sets the UI scoped event bus.\n         */\n        void setUIEventBus(EventBus.UIEventBus uiEventBus);\n    }\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/EventBusListener.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events;\n\nimport java.io.Serializable;\n\n/**\n * Interface to be implemented by listeners that want to subscribe to an {@link org.vaadin.spring.events.EventBus}.\n *\n * @param <T> type of event payloads that the listener is interested in receiving.\n * @author Petter Holmström (petter@vaadin.com)\n */\npublic interface EventBusListener<T> extends Serializable {\n\n    /**\n     * Called when an event has been received.\n     *\n     * @param event the event, never {@code null}.\n     */\n    void onEvent(Event<T> event);\n\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/EventBusListenerMethodFilter.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events;\n\n/**\n * <p>\n * A method annotated with <code>@EventBusListenerMethod</code> will be invoked if it is\n * subscribed to the <code>EventBus</code> that published the <code>Event</code>\n * (or <code>Object</code> payload).  That method will oftentimes employ filtering code\n * in the method internals, because of the possibility that multiple annotated methods\n * might listen to same the <code>Event</code>.\n * </p>\n * <p>\n * As a convenience, an implementation of this filter may be defined in\n * {@link org.vaadin.spring.events.annotation.EventBusListenerMethod#filter()}\n * and stand in place of such filtering code.\n * </p>\n * @author Chris Phillipson (fastnsilver@gmail.com)\n *\n */\npublic interface EventBusListenerMethodFilter {\n\n    /**\n     * Criteria used to influence when an <code>@EventBusListenerMethod</code>\n     * annotated method with this <code>filter</code> defined will execute\n     * @param event EventBus event\n     * @return true if filtering condition met; false otherwise\n     */\n    boolean filter(Event<?> event);\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/EventScope.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events;\n\n/**\n * Enumeration of event scopes.\n *\n * @author Petter Holmström (petter@vaadin.com)\n */\npublic enum EventScope {\n    /**\n     * The event is application wide.\n     */\n    APPLICATION,\n\n    /**\n     * The event is specific to the current (Vaadin) session.\n     */\n    SESSION,\n\n    /**\n     * The event is specific to the current UI.\n     */\n    UI,\n\n    /**\n     * Undefined event scope. An internal event scope used only when no scope has been explicitly defined.\n     *\n     * @see org.vaadin.spring.events.annotation.EventBusListenerMethod#scope()\n     */\n    UNDEFINED\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/ExactTopicFilter.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events;\n\n/**\n * An implementation of {@link org.vaadin.spring.events.TopicFilter}\n * which validates the topics with an exact match (equals).\n * \n * @author Marco Luthardt (marco.luthardt@iandme.net)\n */\npublic class ExactTopicFilter implements TopicFilter {\n\n    @Override\n    public boolean validTopic(String eventTopic, String listenerTopic) {\n        return eventTopic.equals(listenerTopic);\n    }\n\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/HierachyTopicFilter.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events;\n\n/**\n * An implementation of {@link org.vaadin.spring.events.TopicFilter}\n * which validates the topics hierarchical. This means, that the\n * listener filter will be checked as prefixed substring against\n * the event topic.\n * \n * <ol>\n *   <li>match: <code>eventTopic = \"foo.bar\"</code> and <code>listenerTopic = \"foo\"</code></li>\n *   <li>no match: <code>eventTopic = \"foo\"</code> and <code>listenerTopic = \"foo.bar\"</code></li>\n *   <li>no match: <code>eventTopic = \"foo.bar\"</code> and <code>listenerTopic = \"foo.not\"</code></li>\n * </ol>\n * \n * @author Marco Luthardt (marco.luthardt@iandme.net)\n */\npublic class HierachyTopicFilter implements TopicFilter {\n\n    @Override\n    public boolean validTopic(String eventTopic, String listenerTopic) {\n        return eventTopic.startsWith(listenerTopic);\n    }\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/NoEventBusListenerMethodFilter.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events;\n\n\n/**\n * A default filter implementation which always returns true.\n * @author Chris Phillipson (fastnsilver@gmail.com)\n * @see org.vaadin.spring.events.annotation.EventBusListenerMethod#scope()\n */\npublic class NoEventBusListenerMethodFilter implements EventBusListenerMethodFilter {\n\n    @Override\n    public boolean filter(Event<?> event) {\n        return true;\n    }\n\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/TopicFilter.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events;\n\n/**\n * The interface defines a method to validate a given event topic\n * an listener topic. The event topic is provided when publishing\n * an event and the listener topic by the {@link org.vaadin.spring.events.annotation.EventBusListenerTopic} \n * annotation. An implementation of this interface can be used as \n * parameter of this annotation.\n * \n * @author Marco Luthardt (marco.luthardt@iandme.net)\n * @see org.vaadin.spring.events.annotation.EventBusListenerTopic\n */\npublic interface TopicFilter {\n\n    /**\n     * Validates the given event topic against the listener topic.\n     * \n     * @param eventTopic    the topic provided by while publishing an event, never {@code null}\n     * @param listenerTopic the topic of the listener method, never {@code null}\n     * \n     * @return true true if the event topic matches the listener topic, otherwise false\n     */\n    boolean validTopic(String eventTopic, String listenerTopic);\n\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/annotation/EnableEventBus.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events.annotation;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\nimport org.springframework.context.annotation.Import;\nimport org.vaadin.spring.events.config.EventBusConfiguration;\n\n@Target(ElementType.TYPE)\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\n@Import(EventBusConfiguration.class)\npublic @interface EnableEventBus {\n\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/annotation/EventBusListenerMethod.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events.annotation;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\nimport org.vaadin.spring.events.EventBus;\nimport org.vaadin.spring.events.EventBusListener;\nimport org.vaadin.spring.events.EventBusListenerMethodFilter;\nimport org.vaadin.spring.events.EventScope;\nimport org.vaadin.spring.events.NoEventBusListenerMethodFilter;\n\n/**\n * Annotation to be placed on event bus listener methods. A listener method must always conform to one of the following method signatures:\n * <ol>\n *   <li><code>myMethodName({@link org.vaadin.spring.events.Event Event}&lt;MyPayloadType&gt;)</code></li>\n *   <li><code>myMethodName(MyPayloadType)</code></li>\n * </ol>\n * A listener method can have any visibility and any return type.\n *\n * @author Petter Holmström (petter@vaadin.com)\n * @see org.vaadin.spring.events.EventBusListener\n * @see EventBus#subscribe(Object)\n * @see EventBus#subscribe(Object, boolean)\n */\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\npublic @interface EventBusListenerMethod {\n\n    /**\n     * The default scope of a listener method is <code>EventScope.UNDEFINED</code>\n     * This means that listener will listen for any {@link EventScope} if {@link EventBus#subscribe(EventBusListener, boolean)} is set to propagate event\n     */\n    EventScope scope() default EventScope.UNDEFINED;\n\n    Class<? extends EventBusListenerMethodFilter> filter() default NoEventBusListenerMethodFilter.class;\n    \n    /**\n     * Filter by source class \n     */\n    Class<?>[] source() default {};\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/annotation/EventBusListenerTopic.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events.annotation;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\nimport org.vaadin.spring.events.ExactTopicFilter;\nimport org.vaadin.spring.events.TopicFilter;\n\n/**\n * Annotation to be placed on event bus listener methods, additional to\n * the {@link org.vaadin.spring.events.annotation.EventBusListenerMethod} annotation.\n * A topic is specified as string which will be defined when publishing an event.\n * Each method annotated with this annotation and the corresponding topic will be\n * called as listener.\n * \n * Topics can be filtered with implementations of the {@link org.vaadin.spring.events.TopicFilter} interface.\n * \n * @author Marco Luthardt (marco.luthardt@iandme.net)\n * @see org.vaadin.spring.events.annotation.EventBusListenerMethod\n * @see org.vaadin.spring.events.TopicFilter\n */\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\npublic @interface EventBusListenerTopic {\n\n    /**\n     * A topic is a string which can be specified while publishing an event. The\n     * method will only called when the topic matches the given String in the\n     * published method.\n     */\n    String topic() default \"\";\n\n    /**\n     * The filter to be used to validate the published and listener topic.\n     * \n     * @return an implementation of the {@link org.vaadin.spring.events.TopicFilter} interface.\n     */\n    Class<? extends TopicFilter> filter() default ExactTopicFilter.class;\n\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/annotation/EventBusProxy.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events.annotation;\n\nimport org.springframework.beans.factory.annotation.Qualifier;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Inherited;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * Qualifier to be used to indicate that a proxy of an {@link org.vaadin.spring.events.EventBus} should be injected.\n *\n * @author Petter Holmström (petter@vaadin.com)\n */\n@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})\n@Retention(RetentionPolicy.RUNTIME)\n@Inherited\n@Documented\n@Qualifier\npublic @interface EventBusProxy {\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/config/EventBusConfiguration.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events.config;\n\nimport com.vaadin.flow.spring.scopes.VaadinSessionScope;\nimport com.vaadin.flow.spring.scopes.VaadinUIScope;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Primary;\nimport org.springframework.context.annotation.Scope;\nimport org.springframework.context.annotation.ScopedProxyMode;\nimport org.vaadin.spring.events.EventBus;\nimport org.vaadin.spring.events.annotation.EventBusProxy;\nimport org.vaadin.spring.events.internal.ScopedEventBus;\nimport org.vaadin.spring.events.support.VaadinEventBusAwareProcessor;\n\n/**\n * Configuration class to configure the Spring Vaadin Eventbus\n *\n * @author Gert-Jan Timmer (gjr.timmer@gmail.com)\n */\n@Configuration\npublic class EventBusConfiguration {\n\n    @Bean\n    VaadinEventBusAwareProcessor vaadinEventBusProcessor() {\n        return new VaadinEventBusAwareProcessor();\n    }\n\n    @Bean\n    EventBus.ApplicationEventBus applicationEventBus() {\n        return new ScopedEventBus.DefaultApplicationEventBus();\n    }\n\n    @Bean\n    @Scope(value = VaadinSessionScope.VAADIN_SESSION_SCOPE_NAME, proxyMode = ScopedProxyMode.INTERFACES)\n    @EventBusProxy\n    EventBus.SessionEventBus proxiedSessionEventBus() {\n        return sessionEventBus();\n    }\n\n    @Bean\n    @Scope(value = VaadinSessionScope.VAADIN_SESSION_SCOPE_NAME, proxyMode = ScopedProxyMode.NO)\n    @Primary\n    EventBus.SessionEventBus sessionEventBus() {\n        return new ScopedEventBus.DefaultSessionEventBus(applicationEventBus());\n    }\n\n    @Bean\n    @Scope(value = VaadinUIScope.VAADIN_UI_SCOPE_NAME, proxyMode = ScopedProxyMode.INTERFACES)\n    @EventBusProxy\n    EventBus.UIEventBus proxiedUiEventBus() {\n        return uiEventBus();\n    }\n\n    @Bean\n    @Scope(value = VaadinUIScope.VAADIN_UI_SCOPE_NAME, proxyMode = ScopedProxyMode.NO)\n    @Primary\n    EventBus.UIEventBus uiEventBus() {\n        return new ScopedEventBus.DefaultUIEventBus(sessionEventBus());\n    }\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/internal/AbstractListenerWrapper.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events.internal;\n\nimport org.vaadin.spring.events.Event;\nimport org.vaadin.spring.events.EventBus;\n\n/**\n * Base implementation of {@link org.vaadin.spring.events.internal.ListenerCollection.Listener} that implements\n * the {@link #supports(org.vaadin.spring.events.Event)}  method. An event is supported if:\n * <ul>\n * <li>The payload type of the listener is either the same type as, or a supertype of, the payload type of the event</li>\n * <li>The listener allows propagating events, or the event was originally published on event bus that the listener was subscribed to</li>\n * </ul>\n *\n * @author Petter Holmström (petter@vaadin.com)\n */\nabstract class AbstractListenerWrapper implements ListenerCollection.Listener {\n\n    private static final long serialVersionUID = 6211420845165980671L;\n\n    private final EventBus owningEventBus;\n\n    private final Object listenerTarget;\n\n    private final boolean includingPropagatingEvents;\n\n    private final String topic;\n\n    AbstractListenerWrapper(EventBus owningEventBus, Object listenerTarget, String topic, boolean includingPropagatingEvents) {\n        this.owningEventBus = owningEventBus;\n        this.topic = topic;\n        this.listenerTarget = listenerTarget;\n        this.includingPropagatingEvents = includingPropagatingEvents;\n    }\n\n    /**\n     * Gets the payload type of the listener.\n     */\n    protected abstract Class<?> getPayloadType();\n\n    /**\n     * Gets the target object that this listener is wrapping.\n     */\n    public Object getListenerTarget() {\n        return listenerTarget;\n    }\n\n    @Override\n    public boolean supports(Event<?> event) {\n        final Class<?> eventPayloadType = event.getPayload().getClass();\n        return (event.getTopic().equals(topic) || topic == null) &&\n                getPayloadType().isAssignableFrom(eventPayloadType) &&\n                (includingPropagatingEvents || event.getEventBus().equals(owningEventBus));\n    }\n\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/internal/ClassUtils.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events.internal;\n\n/**\n * Utility methods for working with classes and class members.\n *\n * @author Petter Holmström (petter@vaadin.com)\n */\nfinal class ClassUtils {\n\n    private ClassUtils() {\n    }\n\n    /**\n     * Visitor interface used with {@link ClassUtils#visitClassHierarchy(ClassUtils.ClassVisitor, Class)}.\n     */\n    public interface ClassVisitor {\n        void visit(Class<?> clazz);\n    }\n\n    /**\n     * Visits the entire class hierarchy from {@code subClass} to {@code Object}.\n     *\n     * @param visitor  the visitor to use, must not be {@code null}.\n     * @param subClass the class whose hierarchy is to be visited, must not be {@code null}.\n     */\n    static void visitClassHierarchy(ClassVisitor visitor, Class<?> subClass) {\n        Class<?> visitedClass = subClass;\n        while (visitedClass.getSuperclass() != null) {\n            visitor.visit(visitedClass);\n            visitedClass = visitedClass.getSuperclass();\n        }\n    }\n}"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/internal/EventBusListenerWrapper.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events.internal;\n\nimport org.springframework.core.GenericTypeResolver;\nimport org.springframework.util.Assert;\nimport org.vaadin.spring.events.Event;\nimport org.vaadin.spring.events.EventBus;\nimport org.vaadin.spring.events.EventBusListener;\n\n/**\n * Implementation of {@link org.vaadin.spring.events.internal.AbstractListenerWrapper} that wraps a single\n * {@link org.vaadin.spring.events.EventBusListener} instance.\n *\n * @author Petter Holmström (petter@vaadin.com)\n */\nclass EventBusListenerWrapper extends AbstractListenerWrapper {\n\n    private static final long serialVersionUID = 8964309195124823892L;\n    private final Class<?> payloadType;\n\n    EventBusListenerWrapper(EventBus owningEventBus, EventBusListener<?> listenerTarget, String topic, boolean includingPropagatingEvents) {\n        super(owningEventBus, listenerTarget, topic, includingPropagatingEvents);\n        payloadType = GenericTypeResolver.resolveTypeArgument(listenerTarget.getClass(), EventBusListener.class);\n        Assert.notNull(payloadType, \"Could not resolve payload type\");\n    }\n\n    @Override\n    @SuppressWarnings(\"rawtypes\")\n    public EventBusListener getListenerTarget() {\n        return (EventBusListener) super.getListenerTarget();\n    }\n\n    @Override\n    protected Class<?> getPayloadType() {\n        return payloadType;\n    }\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public void publish(Event<?> event) {\n        getListenerTarget().onEvent(event);\n    }\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/internal/ListenerCollection.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events.internal;\n\nimport java.io.Serializable;\nimport java.util.*;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.vaadin.spring.events.Event;\n\n/**\n * A collection of listeners. Intended only for internal use by the framework.\n *\n * @author Petter Holmström (petter@vaadin.com)\n */\nclass ListenerCollection implements Serializable {\n\n    private static final long serialVersionUID = -6237902400879667320L;\n    private final Logger logger = LoggerFactory.getLogger(getClass());\n    private final Set<Listener> listeners = new HashSet<Listener>();\n    private final Set<Listener> weakListeners = Collections.newSetFromMap(new WeakHashMap<Listener, Boolean>());\n\n    /**\n     * Interface defining a listener.\n     */\n    public interface Listener extends Serializable {\n\n        /**\n         * Checks if this listener supports the specified event.\n         *\n         * @param event the event to check, never {@code null}.\n         * @return true if the event is supported, false otherwise.\n         */\n        boolean supports(Event<?> event);\n\n        /**\n         * Publishes the event to the listener.\n         *\n         * @param event the event to publish, never {@code null}.\n         */\n        void publish(Event<?> event);\n    }\n\n    /**\n     * Interface defining a listener filter.\n     */\n    public interface ListenerFilter {\n        /**\n         * Checks if the specified listener passes the filter.\n         *\n         * @param listener the listener to check, never {@code null}.\n         * @return true if the listener passes the filter, false otherwise.\n         */\n        boolean passes(Listener listener);\n    }\n\n    /**\n     * Adds the specified {@link org.vaadin.spring.events.internal.ListenerCollection.Listener} to the listener\n     * collection.\n     *\n     * @param listener the listener to add, never {@code null}.\n     * @see #remove(org.vaadin.spring.events.internal.ListenerCollection.Listener)\n     */\n    void add(Listener listener) {\n        logger.trace(\"Adding listener [{}]\", listener);\n        synchronized (listeners) {\n            listeners.add(listener);\n        }\n    }\n\n    /**\n     * Adds the specified {@link org.vaadin.spring.events.internal.ListenerCollection.Listener} to the listener\n     * collection,\n     * using a weak reference. This means the listener does not need to be removed to be eligible for garbage\n     * collection.\n     *\n     * @param listener the listener to add, never {@code null}.\n     */\n    void addWithWeakReference(Listener listener) {\n        logger.trace(\"Adding listener [{}] using a weak reference\", listener);\n        synchronized (weakListeners) {\n            weakListeners.add(listener);\n        }\n    }\n\n    /**\n     * Removes a {@link org.vaadin.spring.events.internal.ListenerCollection.Listener} previously added by \n     * {@link #add(org.vaadin.spring.events.internal.ListenerCollection.Listener)}.\n     * If no listener definition is found in the collection, nothing happens.\n     *\n     * @param listener the listener to remove, never {@code null}.\n     * @see #add(org.vaadin.spring.events.internal.ListenerCollection.Listener)\n     */\n    void remove(Listener listener) {\n        logger.trace(\"Removing listener [{}]\", listener);\n        synchronized (listeners) {\n            listeners.remove(listener);\n        }\n        synchronized (weakListeners) {\n            weakListeners.remove(listener);\n        }\n    }\n\n    /**\n     * Removes all {@link org.vaadin.spring.events.internal.ListenerCollection.Listener}s that pass the specified filter\n     * and that were previously added by\n     * {@link #add(org.vaadin.spring.events.internal.ListenerCollection.Listener)}.\n     *\n     * @param filter the filter that specifies which listeners to remove, never {@code null}.\n     */\n    void removeAll(ListenerFilter filter) {\n        synchronized (listeners) {\n            removeFilteredListenersFromSet(filter, listeners);\n        }\n        synchronized (weakListeners) {\n            removeFilteredListenersFromSet(filter, weakListeners);\n        }\n    }\n\n    /**\n     * Removes all {@link org.vaadin.spring.events.internal.ListenerCollection.Listener}s from the collection.\n     */\n    void clear() {\n        synchronized (listeners) {\n            listeners.clear();\n        }\n        synchronized (weakListeners) {\n            weakListeners.clear();\n        }\n    }\n\n    /**\n     * Publishes the specified {@code event} to all\n     * {@link org.vaadin.spring.events.internal.ListenerCollection.Listener}s that support it.\n     *\n     * @param event the event to publish, never {@code null}.\n     * @see org.vaadin.spring.events.internal.ListenerCollection.Listener#publish(org.vaadin.spring.events.Event)\n     * @see org.vaadin.spring.events.internal.ListenerCollection.Listener#supports(org.vaadin.spring.events.Event)\n     */\n    public void publish(Event<?> event) {\n        Set<Listener> interestedListeners = new HashSet<Listener>();\n        synchronized (listeners) {\n            addSupportedListenersToSet(listeners, interestedListeners, event);\n        }\n        synchronized (weakListeners) {\n            addSupportedListenersToSet(weakListeners, interestedListeners, event);\n        }\n        if (interestedListeners.isEmpty()) {\n            logger.debug(\"No listeners supported event [{}]\", event);\n        } else {\n            for (Listener listener : interestedListeners) {\n                logger.trace(\"Publishing event [{}] to listener [{}]\", event, listener);\n                listener.publish(event);\n            }\n        }\n    }\n\n    private <T> void addSupportedListenersToSet(Set<Listener> candidateListeners, Set<Listener> selectedListeners,\n        Event<T> event) {\n        for (Listener candidateListener : candidateListeners) {\n            if (candidateListener.supports(event)) {\n                logger.trace(\"Listener [{}] supports event [{}]\", candidateListener, event);\n                selectedListeners.add(candidateListener);\n            }\n        }\n    }\n\n    private void removeFilteredListenersFromSet(ListenerFilter filter, Set<Listener> listenerSet) {\n        for (Iterator<Listener> it = listenerSet.iterator(); it.hasNext();) {\n            Listener listener = it.next();\n            if (filter.passes(listener)) {\n                logger.trace(\"Removing listener [{}]\", listener);\n                it.remove();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/internal/MethodListenerWrapper.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events.internal;\n\nimport org.vaadin.spring.events.*;\nimport org.vaadin.spring.events.annotation.EventBusListenerMethod;\nimport org.vaadin.spring.events.annotation.EventBusListenerTopic;\n\nimport java.io.IOException;\nimport java.io.ObjectInputStream;\nimport java.io.ObjectOutputStream;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.ParameterizedType;\n\n/**\n * Implementation of {@link org.vaadin.spring.events.internal.AbstractListenerWrapper} that wraps an object\n * that contains a method annotated with {@link org.vaadin.spring.events.annotation.EventBusListenerMethod}. If the object\n * contains multiple listener methods, multiple instances of this class should be created.\n *\n * @author Petter Holmström (petter@vaadin.com)\n */\nclass MethodListenerWrapper extends AbstractListenerWrapper {\n\n    private static final long serialVersionUID = -3624543380547361337L;\n    private final Class<?> payloadType;\n    private final boolean payloadMethod;\n    private transient Method listenerMethod;\n    private final String topic;\n\n    MethodListenerWrapper(EventBus owningEventBus, Object listenerTarget, String topic, boolean includingPropagatingEvents, Method listenerMethod) {\n        super(owningEventBus, listenerTarget, topic, includingPropagatingEvents);\n        this.topic = topic;\n        if (listenerMethod.getParameterTypes()[0] == Event.class) {\n            ParameterizedType type = (ParameterizedType) listenerMethod.getGenericParameterTypes()[0];\n            payloadType = (Class<?>) type.getActualTypeArguments()[0];\n            payloadMethod = false;\n        } else {\n            payloadType = listenerMethod.getParameterTypes()[0];\n            payloadMethod = true;\n        }\n        this.listenerMethod = listenerMethod;\n    }\n\n    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {\n        ois.defaultReadObject();\n        // TODO Read listener method info and look up method\n    }\n\n    private void writeObject(ObjectOutputStream oos) throws IOException {\n        oos.defaultWriteObject();\n        // TODO Write listener method info\n    }\n\n    @Override\n    public Class<?> getPayloadType() {\n        return payloadType;\n    }\n\n    @Override\n    public void publish(Event<?> event) {\n        listenerMethod.setAccessible(true);\n        try {\n            if (payloadMethod) {\n                listenerMethod.invoke(getListenerTarget(), event.getPayload());\n            } else {\n                listenerMethod.invoke(getListenerTarget(), event);\n            }\n        } catch (IllegalAccessException e) {\n            throw new RuntimeException(\"Could not access listener method \" + listenerMethod.getName());\n        } catch (InvocationTargetException e) {\n            Throwable targetException = e.getTargetException();\n            if (targetException instanceof RuntimeException) {\n                throw (RuntimeException) targetException;\n            } else {\n                throw new RuntimeException(\"A checked exception occurred while invoking listener method \" + listenerMethod.getName(), targetException);\n            }\n        }\n    }\n\n    @Override\n    public boolean supports(Event<?> event) {\n        boolean supports = super.supports(event);\n        try {\n            if (listenerMethod.isAnnotationPresent(EventBusListenerMethod.class)) {\n                supports = supports && isInterestedListenerMethod(event);\n            }\n\n            if (topic != null) {\n                return supports;\n            }\n\n            if (listenerMethod.isAnnotationPresent(EventBusListenerTopic.class) && supports) {\n                supports = isInTopic(event);\n            } else if (!event.getTopic().isEmpty()) {\n                supports = false;\n            }\n        } catch (Exception e) {\n            throw new RuntimeException(\"A checked exception occurred while invoking listener method \" + listenerMethod.getName(), e);\n        }\n        return supports;\n    }\n\n    private boolean isInterestedListenerMethod(Event<?> event) throws InstantiationException, IllegalAccessException {\n        EventBusListenerMethod annotation = listenerMethod.getAnnotation(EventBusListenerMethod.class);\n        EventBusListenerMethodFilter filter = annotation.filter().newInstance();\n        EventScope scope = annotation.scope();\n        if (scope.equals(EventScope.UNDEFINED)) {\n            scope = event.getScope();\n        }\n        return filter.filter(event)\n                && event.getScope().equals(scope) && isFromSource(event, annotation.source());\n    }\n\n    private boolean isFromSource(Event<?> event, Class<?>[] sources) {\n        if (sources.length == 0) {\n            return true;\n        }\n\n        boolean result = false;\n\n        for (int i = 0; i < sources.length && !result; i++) {\n            result |= sources[i].isAssignableFrom(event.getSource().getClass());\n        }\n\n        return result;\n    }\n\n    private boolean isInTopic(Event<?> event) throws InstantiationException, IllegalAccessException {\n        EventBusListenerTopic annotation = listenerMethod.getAnnotation(EventBusListenerTopic.class);\n        TopicFilter filter = annotation.filter().newInstance();\n        return filter.validTopic(event.getTopic(), annotation.topic());\n    }\n\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/internal/ScopedEventBus.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events.internal;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.aop.framework.Advised;\nimport org.springframework.aop.support.AopUtils;\nimport org.vaadin.spring.events.Event;\nimport org.vaadin.spring.events.EventBus;\nimport org.vaadin.spring.events.EventBusListener;\nimport org.vaadin.spring.events.EventScope;\nimport org.vaadin.spring.events.annotation.EventBusListenerMethod;\n\nimport javax.annotation.PreDestroy;\nimport java.io.Serializable;\nimport java.lang.reflect.Method;\n\n/**\n * Implementation of {@link org.vaadin.spring.events.EventBus} that publishes events with one specific\n * {@link org.vaadin.spring.events.EventScope}.\n * A scoped event bus can also have a parent event bus, in which case all events published on the parent bus will\n * propagate to the scoped event bus as well.\n *\n * @author Petter Holmström (petter@vaadin.com)\n */\npublic abstract class ScopedEventBus implements EventBus, Serializable {\n\n    private static final long serialVersionUID = -582697574672947883L;\n    private final Logger logger = LoggerFactory.getLogger(getClass());\n    private final EventScope eventScope;\n\n    private final ListenerCollection listeners = new ListenerCollection();\n\n    private EventBus parentEventBus;\n    private EventBusListener<Object> parentListener = new EventBusListener<Object>() {\n\n        private static final long serialVersionUID = -8276470908536582989L;\n\n        @Override\n        public void onEvent(final Event<Object> event) {\n            logger.debug(\"Propagating event [{}] from parent event bus [{}] to event bus [{}]\", event, parentEventBus,\n                    ScopedEventBus.this);\n            listeners.publish(event);\n        }\n\n    };\n\n    /**\n     * @param scope the scope of the events that this event bus handles.\n     */\n    public ScopedEventBus(EventScope scope) {\n        this(scope, null);\n    }\n\n    /**\n     * @param scope          the scope of the events that this event bus handles.\n     * @param parentEventBus the parent event bus to use, may be {@code null};\n     */\n    public ScopedEventBus(EventScope scope, EventBus parentEventBus) {\n        eventScope = scope;\n        this.parentEventBus = parentEventBus;\n        if (parentEventBus != null) {\n            if (AopUtils.isJdkDynamicProxy(parentEventBus)) {\n                logger.debug(\"Parent event bus [{}] is proxied, trying to get the real EventBus instance\",\n                        parentEventBus);\n                try {\n                    this.parentEventBus = (EventBus) ((Advised) parentEventBus).getTargetSource().getTarget();\n                } catch (Exception e) {\n                    logger.error(\"Could not get target EventBus from proxy\", e);\n                    throw new RuntimeException(\"Could not get parent event bus\", e);\n                }\n            }\n            logger.debug(\"Using parent event bus [{}]\", this.parentEventBus);\n            this.parentEventBus.subscribe(parentListener);\n        }\n    }\n\n    @PreDestroy\n    void destroy() {\n        logger.trace(\"Destroying event bus [{}] and removing all listeners\", this);\n        listeners.clear();\n        if (parentEventBus != null) {\n            parentEventBus.unsubscribe(parentListener);\n        }\n    }\n\n    @Override\n    public EventScope getScope() {\n        return eventScope;\n    }\n\n    @Override\n    public <T> void publish(Object sender, T payload) {\n        publish(\"\", sender, payload);\n    }\n\n    @Override\n    public <T> void publish(String topic, Object sender, T payload) {\n        logger.debug(\"Publishing payload [{}] from sender [{}] on event bus [{}] in topic  [{}]\", payload, sender, this,\n                topic);\n        listeners.publish(new Event<T>(this, sender, payload, topic));\n    }\n\n    @Override\n    public <T> void publish(EventScope scope, Object sender, T payload) throws UnsupportedOperationException {\n        publish(scope, \"\", sender, payload);\n    }\n\n    @Override\n    public <T> void publish(EventScope scope, String topic, Object sender, T payload)\n            throws UnsupportedOperationException {\n        logger.debug(\"Trying to publish payload [{}] from sender [{}] using scope [{}] on event bus [{}] in topic [{}]\",\n                payload, sender, scope, this, topic);\n\n        if (eventScope.equals(scope)) {\n            publish(topic, sender, payload);\n        } else if (parentEventBus != null) {\n            parentEventBus.publish(scope, topic, sender, payload);\n        } else {\n            logger.warn(\"Could not publish payload with scope [{}] on event bus [{}]\", scope, this);\n            throw new UnsupportedOperationException(\"Could not publish event with scope \" + scope);\n        }\n    }\n\n    @Override\n    public <T> void subscribe(EventBusListener<T> listener) {\n        subscribe(listener, true);\n    }\n\n    @Override\n    public <T> void subscribeWithWeakReference(EventBusListener<T> listener) {\n        subscribeWithWeakReference(listener, true);\n    }\n\n    @Override\n    public <T> void subscribe(EventBusListener<T> listener, String topic) {\n        logger.trace(\"Subscribing listener [{}] to event bus [{}]\", listener, this);\n        listeners.add(new EventBusListenerWrapper(this, listener, topic, true));\n    }\n\n    @Override\n    public <T> void subscribe(EventBusListener<T> listener, boolean includingPropagatingEvents) {\n        logger.trace(\"Subscribing listener [{}] to event bus [{}], includingPropagatingEvents = {}\", listener, this,\n                includingPropagatingEvents);\n        listeners.add(new EventBusListenerWrapper(this, listener, null, includingPropagatingEvents));\n    }\n\n    @Override\n    public <T> void subscribeWithWeakReference(EventBusListener<T> listener, String topic) {\n        logger.trace(\"Subscribing listener [{}] to event bus [{}] with weak reference\",\n                listener, this);\n        listeners.addWithWeakReference(new EventBusListenerWrapper(this, listener, topic, true));\n    }\n\n    @Override\n    public <T> void subscribeWithWeakReference(EventBusListener<T> listener, boolean includingPropagatingEvents) {\n        logger.trace(\"Subscribing listener [{}] to event bus [{}] with weak reference, includingPropagatingEvents = {}\",\n                listener, this, includingPropagatingEvents);\n        listeners.addWithWeakReference(new EventBusListenerWrapper(this, listener, null, includingPropagatingEvents));\n    }\n\n    @Override\n    public void subscribe(Object listener) {\n        subscribe(listener, true);\n    }\n\n    @Override\n    public void subscribe(Object listener, String topic) {\n        subscribe(listener, topic, true, false);\n    }\n\n    @Override\n    public void subscribeWithWeakReference(Object listener, String topic) {\n        subscribe(listener, topic, true, false);\n    }\n\n    @Override\n    public void subscribeWithWeakReference(Object listener) {\n        subscribeWithWeakReference(listener, true);\n    }\n\n    @Override\n    public void subscribe(Object listener, boolean includingPropagatingEvents) {\n        subscribe(listener, null, includingPropagatingEvents, false);\n    }\n\n    @Override\n    public void subscribeWithWeakReference(Object listener, boolean includingPropagatingEvents) {\n        subscribe(listener, null, includingPropagatingEvents, true);\n    }\n\n    private void subscribe(final Object listener, final String topic, final boolean includingPropagatingEvents,\n                           final boolean weakReference) {\n        logger.trace(\"Subscribing listener [{}] to event bus [{}], includingPropagatingEvents = {}, weakReference = {}\",\n                listener, this, includingPropagatingEvents, weakReference);\n\n        final int[] foundMethods = new int[1];\n        ClassUtils.visitClassHierarchy(clazz -> {\n            for (Method m : clazz.getDeclaredMethods()) {\n                if (m.isAnnotationPresent(EventBusListenerMethod.class)) {\n                    if (m.getParameterTypes().length == 1) {\n                        logger.trace(\"Found listener method [{}] in listener [{}]\", m.getName(), listener);\n                        MethodListenerWrapper l = new MethodListenerWrapper(ScopedEventBus.this, listener, topic,\n                                includingPropagatingEvents, m);\n                        if (weakReference) {\n                            listeners.addWithWeakReference(l);\n                        } else {\n                            listeners.add(l);\n                        }\n                        foundMethods[0]++;\n                    } else {\n                        throw new IllegalArgumentException(\n                                \"Listener method \" + m.getName() + \" does not have the required signature\");\n                    }\n                }\n            }\n        }, listener.getClass());\n\n        if (foundMethods[0] == 0) {\n            logger.warn(\"Listener [{}] did not contain a single listener method!\", listener);\n        }\n    }\n\n    @Override\n    public <T> void unsubscribe(EventBusListener<T> listener) {\n        unsubscribe((Object) listener);\n    }\n\n    @Override\n    public void unsubscribe(final Object listener) {\n        logger.trace(\"Unsubscribing listener [{}] from event bus [{}]\", listener, this);\n        listeners.removeAll(l -> (l instanceof AbstractListenerWrapper)\n                && (((AbstractListenerWrapper) l).getListenerTarget() == listener));\n    }\n\n    /**\n     * Gets the parent of this event bus. Events published on the parent bus will also\n     * propagate to the listeners of this event bus.\n     *\n     * @return the parent event bus, or {@code null} if this event bus has no parent.\n     */\n    protected EventBus getParentEventBus() {\n        return parentEventBus;\n    }\n\n    @Override\n    public String toString() {\n        return String.format(\"%s[id=%x, eventScope=%s, parentEventBus=%s]\", getClass().getSimpleName(),\n                System.identityHashCode(this), eventScope, parentEventBus);\n    }\n\n    /**\n     * Default implementation of {@link org.vaadin.spring.events.EventBus.ApplicationEventBus}.\n     */\n    public static class DefaultApplicationEventBus extends ScopedEventBus implements ApplicationEventBus {\n\n        public DefaultApplicationEventBus() {\n            super(EventScope.APPLICATION);\n        }\n    }\n\n    /**\n     * Default implementation of {@link org.vaadin.spring.events.EventBus.SessionEventBus}.\n     */\n    public static class DefaultSessionEventBus extends ScopedEventBus implements SessionEventBus {\n\n        public DefaultSessionEventBus(ApplicationEventBus parentEventBus) {\n            super(EventScope.SESSION, parentEventBus);\n        }\n    }\n\n    /**\n     * Default implementation of {@link org.vaadin.spring.events.EventBus.UIEventBus}.\n     */\n    public static class DefaultUIEventBus extends ScopedEventBus implements UIEventBus {\n\n        public DefaultUIEventBus(SessionEventBus parentEventBus) {\n            super(EventScope.UI, parentEventBus);\n        }\n    }\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/support/ApplicationContextEventBroker.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events.support;\n\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\nimport org.springframework.context.ApplicationEvent;\nimport org.springframework.context.ApplicationListener;\nimport org.vaadin.spring.events.EventBus;\n\n/**\n * An {@link org.springframework.context.ApplicationListener} that will forward all received events to an {@link org.vaadin.spring.events.EventBus}.\n *\n * @author Petter Holmström (petter@vaadin.com)\n */\npublic class ApplicationContextEventBroker implements ApplicationListener<ApplicationEvent> {\n\n    private Log logger = LogFactory.getLog(getClass());\n\n    private final EventBus eventBus;\n\n    public ApplicationContextEventBroker(EventBus eventBus) {\n        this.eventBus = eventBus;\n    }\n\n    @Override\n    public void onApplicationEvent(ApplicationEvent event) {\n        logger.debug(String.format(\"Propagating application event [%s] to event bus [%s]\", event, this));\n        eventBus.publish(event.getSource(), event);\n    }\n}\n"
  },
  {
    "path": "eventbus/src/main/java/org/vaadin/spring/events/support/VaadinEventBusAwareProcessor.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events.support;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.beans.factory.config.BeanPostProcessor;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.context.ConfigurableApplicationContext;\nimport org.vaadin.spring.events.EventBus;\nimport org.vaadin.spring.events.EventBusAware;\n\nimport java.security.AccessControlContext;\nimport java.security.AccessController;\nimport java.security.PrivilegedAction;\n\n/**\n * {@link org.springframework.beans.factory.config.BeanPostProcessor}\n * implementation that passes the corresponding EventBus to beans that\n * implement the one of the {@link org.vaadin.spring.events.EventBusAware} interfaces\n *\n * @author Gert-Jan Timmer (gjr.timmer@gmail.com)\n * @author Petter Holmström (petter@vaadin.com)\n */\npublic class VaadinEventBusAwareProcessor implements ApplicationContextAware, BeanPostProcessor {\n\n    private ConfigurableApplicationContext applicationContext;\n\n    @Override\n    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n        this.applicationContext = (ConfigurableApplicationContext) applicationContext;\n    }\n\n    @Override\n    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {\n        AccessControlContext acc = null;\n\n        if (System.getSecurityManager() != null && (bean instanceof EventBusAware)) {\n            acc = this.applicationContext.getBeanFactory().getAccessControlContext();\n        }\n\n        if (acc != null) {\n            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {\n                invokeAwareInterfaces(bean);\n                return null;\n            }, acc);\n        } else {\n            invokeAwareInterfaces(bean);\n        }\n\n        return bean;\n    }\n\n    @Override\n    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {\n        return bean;\n    }\n\n    private void invokeAwareInterfaces(Object bean) {\n        if (bean instanceof EventBusAware) {\n\n            if (bean instanceof EventBusAware.ApplicationEventBusAware) {\n                ((EventBusAware.ApplicationEventBusAware) bean).setApplicationEventBus(this.applicationContext.getBean(EventBus.ApplicationEventBus.class));\n            }\n            if (bean instanceof EventBusAware.SessionEventBusAware) {\n                ((EventBusAware.SessionEventBusAware) bean).setSessionEventBus(this.applicationContext.getBean(EventBus.SessionEventBus.class));\n            }\n            if (bean instanceof EventBusAware.UIEventBusAware) {\n                ((EventBusAware.UIEventBusAware) bean).setUIEventBus(this.applicationContext.getBean(EventBus.UIEventBus.class));\n            }\n\n        }\n    }\n}\n"
  },
  {
    "path": "eventbus/src/test/java/org/vaadin/spring/events/integration/ScopedEventBusIntegrationTest.java",
    "content": "package org.vaadin.spring.events.integration;\n\nimport com.vaadin.flow.component.UI;\nimport com.vaadin.flow.server.VaadinService;\nimport com.vaadin.flow.server.VaadinSession;\nimport com.vaadin.flow.spring.SpringVaadinSession;\nimport com.vaadin.flow.spring.annotation.EnableVaadin;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mockito;\nimport org.mockito.MockitoAnnotations;\nimport org.springframework.beans.factory.BeanCreationException;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.vaadin.spring.events.EventBus;\nimport org.vaadin.spring.events.config.EventBusConfiguration;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.mockito.Mockito.when;\n\n/**\n * Test cases for the different event bus scopes\n *\n * @author erik@vaadin.com\n * @since 14/02/2019\n */\n@ExtendWith(SpringExtension.class)\n@ContextConfiguration(classes = {EventBusConfiguration.class, ScopedEventBusIntegrationTest.Config.class})\nclass ScopedEventBusIntegrationTest {\n\n    @Configuration\n    @EnableVaadin\n    public static class Config {\n    }\n\n    public static class TestSession extends SpringVaadinSession {\n        TestSession() {\n            super(Mockito.mock(VaadinService.class));\n        }\n\n        @Override\n        public boolean hasLock() {\n            return true;\n        }\n\n        @Override\n        public void lock() {\n        }\n\n        @Override\n        public void unlock() {\n        }\n    }\n\n    private static int uiId = 0;\n\n    @Autowired\n    ApplicationContext applicationContext;\n\n    @BeforeEach\n    public void setUp() {\n        MockitoAnnotations.initMocks(this);\n        VaadinSession.setCurrent(new TestSession());\n        UI.setCurrent(createMockUI());\n    }\n\n    @Test\n    void testSameUIReturnsSameUIEventBus() {\n        EventBus.UIEventBus uiBus = applicationContext.getBean(EventBus.UIEventBus.class);\n        EventBus.UIEventBus uiBus2 = applicationContext.getBean(EventBus.UIEventBus.class);\n        assertEquals(uiBus, uiBus2, \"Same UI should return same UIEventBus\");\n    }\n\n    @Test\n    void testDifferentUIReturnsDifferentUIEventBus() {\n        EventBus.UIEventBus uiBus = applicationContext.getBean(EventBus.UIEventBus.class);\n        UI.setCurrent(createMockUI());\n        EventBus.UIEventBus uiBus2 = applicationContext.getBean(EventBus.UIEventBus.class);\n        assertNotEquals(uiBus, uiBus2, \"Different UIs should return different UIEventBuses\");\n    }\n\n    @Test\n    void testNoUIThrowsBeanCreationException() {\n        UI.setCurrent(null);\n        assertThrows(BeanCreationException.class, () -> applicationContext.getBean(EventBus.UIEventBus.class));\n    }\n\n    @Test\n    void testSameSessionReturnsSameSessionEventBus() {\n        EventBus.SessionEventBus sessionBus = applicationContext.getBean(EventBus.SessionEventBus.class);\n        EventBus.SessionEventBus sessionBus2 = applicationContext.getBean(EventBus.SessionEventBus.class);\n        assertEquals(sessionBus, sessionBus2, \"Same session should return same SessionEventBus\");\n    }\n\n    @Test\n    void testSameSessionDifferentUIReturnsSameSessionEventBus() {\n        EventBus.SessionEventBus sessionBus = applicationContext.getBean(EventBus.SessionEventBus.class);\n        UI.setCurrent(createMockUI());\n        EventBus.SessionEventBus sessionBus2 = applicationContext.getBean(EventBus.SessionEventBus.class);\n        assertEquals(sessionBus, sessionBus2, \"Same session different UIs should return same SessionEventBus\");\n    }\n\n    @Test\n    void testDifferentSessionsReturnDifferentSessionEventBuses() {\n        EventBus.SessionEventBus sessionBus = applicationContext.getBean(EventBus.SessionEventBus.class);\n        VaadinSession.setCurrent(new TestSession());\n        EventBus.SessionEventBus sessionBus2 = applicationContext.getBean(EventBus.SessionEventBus.class);\n        assertNotEquals(sessionBus, sessionBus2, \"Different sessions should return different SessionEventBuses\");\n    }\n\n    @Test\n    void sameApplicationReturnsSameApplicationEventBus() {\n        EventBus.ApplicationEventBus applicationBus = applicationContext.getBean(EventBus.ApplicationEventBus.class);\n        EventBus.ApplicationEventBus applicationBus2 = applicationContext.getBean(EventBus.ApplicationEventBus.class);\n        assertEquals(applicationBus, applicationBus2, \"ApplicationEventBus should always be the same\");\n    }\n\n    @Test\n    void sameApplicationDifferentUIReturnsSameApplicationEventBus() {\n        EventBus.ApplicationEventBus applicationBus = applicationContext.getBean(EventBus.ApplicationEventBus.class);\n        UI.setCurrent(createMockUI());\n        EventBus.ApplicationEventBus applicationBus2 = applicationContext.getBean(EventBus.ApplicationEventBus.class);\n        assertEquals(applicationBus, applicationBus2, \"ApplicationEventBus should always be the same\");\n    }\n\n    @Test\n    void sameApplicationDifferentSessionReturnsSameApplicationEventBus() {\n        EventBus.ApplicationEventBus applicationBus = applicationContext.getBean(EventBus.ApplicationEventBus.class);\n        VaadinSession.setCurrent(new TestSession());\n        EventBus.ApplicationEventBus applicationBus2 = applicationContext.getBean(EventBus.ApplicationEventBus.class);\n        assertEquals(applicationBus, applicationBus2, \"ApplicationEventBus should always be the same\");\n    }\n\n    /**\n     * Creates a new mock UI with a unique ID\n     */\n    private UI createMockUI() {\n        UI ui = Mockito.mock(UI.class);\n        int id = uiId++;\n        when(ui.getUIId()).thenReturn(id);\n        return ui;\n    }\n}\n"
  },
  {
    "path": "eventbus/src/test/java/org/vaadin/spring/events/internal/ScopedEventBusTest.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events.internal;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.ArgumentCaptor;\nimport org.vaadin.spring.events.Event;\nimport org.vaadin.spring.events.EventBusListener;\nimport org.vaadin.spring.events.EventScope;\nimport org.vaadin.spring.events.HierachyTopicFilter;\nimport org.vaadin.spring.events.annotation.EventBusListenerMethod;\nimport org.vaadin.spring.events.annotation.EventBusListenerTopic;\n\nimport static org.junit.jupiter.api.Assertions.*;\nimport static org.mockito.Mockito.*;\n\n/**\n * Test case for {@link org.vaadin.spring.events.internal.ScopedEventBus}.\n *\n * @author Petter Holmström (petter@vaadin.com)\n */\npublic class ScopedEventBusTest {\n\n    ScopedEventBus.DefaultApplicationEventBus applicationEventBus;\n    ScopedEventBus.DefaultSessionEventBus sessionEventBus;\n\n    interface StringListener extends EventBusListener<String> {\n    }\n\n    static class MultipleListeners {\n\n        Event<String> theStringEvent;\n        Event<Integer> theIntegerEvent;\n        String theStringPayload;\n        Integer theIntegerPayload;\n\n        Event<String> theStringEventWithTopic;\n        Event<Integer> theIntegerEventWithTopic;\n        String theStringPayloadWithTopic;\n        Integer theIntegerPayloadWithTopic;\n\n        String theStringPayloadWithTopicFail;\n        Integer theIntegerPayloadWithTopicFail;\n\n        @EventBusListenerMethod\n        void onStringEvent(Event<String> stringEvent) {\n            theStringEvent = stringEvent;\n        }\n\n        @EventBusListenerMethod\n        void onStringPayloadEvent(String stringPayload) {\n            theStringPayload = stringPayload;\n        }\n\n        @EventBusListenerMethod\n        void onIntegerEvent(Event<Integer> integerEvent) {\n            theIntegerEvent = integerEvent;\n        }\n\n        @EventBusListenerMethod\n        void onIntegerPayloadEvent(Integer integerPayload) {\n            theIntegerPayload = integerPayload;\n        }\n\n        @EventBusListenerTopic(topic = \"shouldSucceed\")\n        @EventBusListenerMethod\n        void onStringEventWithTopic(Event<String> stringEvent) {\n            theStringEventWithTopic = stringEvent;\n        }\n\n        @EventBusListenerTopic(topic = \"shouldSucceed\")\n        @EventBusListenerMethod\n        void onStringPayloadEventWithTopic(String stringPayload) {\n            theStringPayloadWithTopic = stringPayload;\n        }\n\n        @EventBusListenerTopic(topic = \"shouldSucceed\")\n        @EventBusListenerMethod\n        void onIntegerEventWithTopic(Event<Integer> integerEvent) {\n            theIntegerEventWithTopic = integerEvent;\n        }\n\n        @EventBusListenerTopic(topic = \"shouldSucceed\", filter = HierachyTopicFilter.class)\n        @EventBusListenerMethod\n        void onIntegerPayloadEventWithTopic(Integer integerPayload) {\n            theIntegerPayloadWithTopic = integerPayload;\n        }\n\n        @EventBusListenerTopic(topic = \"shouldFail\")\n        @EventBusListenerMethod\n        void onStringPayloadEventWithTopicFail(String stringPayload) {\n            theStringPayloadWithTopicFail = stringPayload;\n        }\n\n        @EventBusListenerTopic(topic = \"shouldSucceed.butFail\")\n        @EventBusListenerMethod\n        void onIntegerPayloadEventWithTopicFail(Integer integerPayload) {\n            theIntegerPayloadWithTopicFail = integerPayload;\n        }\n    }\n\n    class TopicStringListener implements EventBusListener<String> {\n\n        Event<String> theStringEvent;\n\n        @Override\n        public void onEvent(Event<String> event) {\n            this.theStringEvent = event;\n        }\n    }\n\n    class TopicIntegerListener implements EventBusListener<Integer> {\n\n        Event<Integer> theIntegerEvent;\n\n        @Override\n        public void onEvent(Event<Integer> event) {\n            this.theIntegerEvent = event;\n        }\n    }\n\n    class TopicListeners {\n\n        String theStringPayload;\n        Integer theIntegerPayload;\n        Event<String> theStringEvent;\n        Event<Integer> theIntegerEvent;\n\n        @EventBusListenerMethod\n        void onStringEvent(String theStringPayload) {\n            this.theStringPayload = theStringPayload;\n        }\n\n        @EventBusListenerMethod\n        void onStringEvent(Event<String> theStringEvent) {\n            this.theStringEvent = theStringEvent;\n        }\n\n        @EventBusListenerMethod\n        void onIntegerEvent(Integer theIntegerPayload) {\n            this.theIntegerPayload = theIntegerPayload;\n        }\n\n        @EventBusListenerMethod\n        void onIntegerEvent(Event<Integer> theIntegerEvent) {\n            this.theIntegerEvent = theIntegerEvent;\n        }\n    }\n\n    static class InvalidListener1 {\n\n        @EventBusListenerMethod\n        void tooFewParameters() {\n        }\n    }\n\n    static class InvalidListener2 {\n\n        @EventBusListenerMethod\n        void tooManyParameters(String parameter1, Integer parameter2) {\n        }\n    }\n\n    @BeforeEach\n    public void setUp() {\n        applicationEventBus = new ScopedEventBus.DefaultApplicationEventBus();\n        sessionEventBus = new ScopedEventBus.DefaultSessionEventBus(applicationEventBus);\n    }\n\n    @AfterEach\n    public void tearDown() {\n        sessionEventBus.destroy();\n        applicationEventBus.destroy();\n    }\n\n    @Test\n    @SuppressWarnings({\"unchecked\", \"rawtypes\"})\n    public void testSubscribeAndPublish() {\n        StringListener stringListener = mock(StringListener.class);\n\n        sessionEventBus.subscribe(stringListener);\n        sessionEventBus.publish(this, \"Hello World\");\n\n        ArgumentCaptor<Event> event = ArgumentCaptor.forClass(Event.class);\n        verify(stringListener).onEvent(event.capture());\n        assertEquals(\"Hello World\", event.getValue().getPayload());\n    }\n\n    @Test\n    public void testSubscribeAndPublishWithListenerMethods() {\n        MultipleListeners listener = new MultipleListeners();\n\n        sessionEventBus.subscribe(listener);\n        sessionEventBus.publish(this, \"Hello World\");\n\n        assertNull(listener.theIntegerEvent);\n        assertNull(listener.theIntegerPayload);\n        assertNotNull(listener.theStringEvent);\n        assertEquals(\"Hello World\", listener.theStringEvent.getPayload());\n        assertEquals(\"Hello World\", listener.theStringPayload);\n    }\n\n    @Test\n    public void testSubscribeAndPublishWithListenerMethodsWithTopic() {\n        MultipleListeners listener = new MultipleListeners();\n\n        sessionEventBus.subscribe(listener);\n        sessionEventBus.publish(\"shouldSucceed\", this, \"Hello World\");\n        sessionEventBus.publish(\"shouldSucceed.int\", this, 10);\n\n        // null because not called with topic\n        assertNull(listener.theStringPayload);\n        assertNull(listener.theStringEvent);\n        assertNull(listener.theIntegerPayload);\n        assertNull(listener.theIntegerEvent);\n\n        // null because topic must fail\n        assertNull(listener.theStringPayloadWithTopicFail);\n        assertNull(listener.theIntegerPayloadWithTopicFail);\n        assertNull(listener.theIntegerEventWithTopic);\n\n        assertNotNull(listener.theStringPayloadWithTopic);\n        assertNotNull(listener.theStringEventWithTopic);\n\n        assertEquals(\"Hello World\", listener.theStringPayloadWithTopic);\n        assertEquals(\"Hello World\", listener.theStringEventWithTopic.getPayload());\n        assertEquals(10, listener.theIntegerPayloadWithTopic.intValue());\n    }\n\n    @Test\n    public void testSubscribeToTopicAndPublishWithTopic() {\n        String topic = \"/news\";\n        String payload = \"Hello World\";\n\n        TopicListeners topicListener = new TopicListeners();\n        applicationEventBus.subscribe(topicListener, topic);\n\n        applicationEventBus.publish(topic, this, payload);\n        assertEquals(payload, topicListener.theStringPayload);\n        assertEquals(payload, topicListener.theStringEvent.getPayload());\n        assertNull(topicListener.theIntegerPayload);\n        assertNull(topicListener.theIntegerEvent);\n    }\n\n    @Test\n    public void testUnsubscribeFromTopicAndPublishWithTopic() {\n        String topic = \"/news\";\n        String payload = \"Hello World\";\n\n        TopicListeners topicListener = new TopicListeners();\n        applicationEventBus.subscribe(topicListener, topic);\n\n        applicationEventBus.publish(topic, this, payload);\n        assertEquals(payload, topicListener.theStringPayload);\n\n        topicListener.theStringPayload = null;\n        applicationEventBus.unsubscribe(topicListener);\n\n        applicationEventBus.publish(topic, this, payload);\n        assertNotEquals(payload, topicListener.theStringPayload);\n    }\n\n    @Test\n    public void testSubscribeToTopicAndPublishWithDifferentTopic() {\n        String topic = \"/news\";\n        String differentTopic = \"/different\";\n        String payload = \"Hello World\";\n\n        TopicListeners topicListener = new TopicListeners();\n        applicationEventBus.subscribe(topicListener, topic);\n\n        applicationEventBus.publish(differentTopic, this, payload);\n        assertNotEquals(payload, topicListener.theStringPayload);\n    }\n\n    @Test\n    public void testSubscribeTopicListenerForTwoTopicsAndPublishWithThoseTopics() {\n        String newsTopic = \"/news\";\n        String counterTopic = \"/counter\";\n        String newsPayload = \"Hello World\";\n        Integer counterPayload = 0;\n\n        TopicListeners topicListener = new TopicListeners();\n        applicationEventBus.subscribe(topicListener, newsTopic);\n        applicationEventBus.subscribe(topicListener, counterTopic);\n\n        applicationEventBus.publish(newsTopic, this, newsPayload);\n        assertEquals(newsPayload, topicListener.theStringPayload);\n        assertNotEquals(counterPayload, topicListener.theIntegerPayload);\n\n        applicationEventBus.publish(counterTopic, this, counterPayload);\n        assertEquals(counterPayload, topicListener.theIntegerPayload);\n    }\n\n    @Test\n    public void testTwoTopicListenersSubscribedForSameTopic() {\n        String topic = \"/news\";\n        String payload = \"Hello World\";\n\n        TopicListeners firstTopicListener = new TopicListeners();\n        TopicListeners secondTopicListener = new TopicListeners();\n\n        applicationEventBus.subscribe(firstTopicListener, topic);\n        applicationEventBus.subscribe(secondTopicListener, topic);\n\n        applicationEventBus.publish(topic, this, payload);\n        assertEquals(payload, firstTopicListener.theStringPayload);\n        assertEquals(payload, firstTopicListener.theStringEvent.getPayload());\n        assertEquals(payload, secondTopicListener.theStringPayload);\n        assertEquals(payload, secondTopicListener.theStringEvent.getPayload());\n    }\n\n    @Test\n    public void testTwoTopicListenersSubscribedForDifferentTopics() {\n        String firstTopic = \"/first\";\n        String secondTopic = \"/second\";\n        String firstPayload = \"first\";\n        String secondPayload = \"second\";\n\n        TopicListeners firstTopicListener = new TopicListeners();\n        TopicListeners secondTopicListener = new TopicListeners();\n\n        applicationEventBus.subscribe(firstTopicListener, firstTopic);\n        applicationEventBus.subscribe(secondTopicListener, secondTopic);\n\n        applicationEventBus.publish(firstTopic, this, firstPayload);\n        assertEquals(firstPayload, firstTopicListener.theStringPayload);\n        assertEquals(firstPayload, firstTopicListener.theStringEvent.getPayload());\n        assertNull(secondTopicListener.theStringPayload);\n        assertNull(secondTopicListener.theStringEvent);\n\n        applicationEventBus.publish(secondTopic, this, secondPayload);\n        assertEquals(secondPayload, secondTopicListener.theStringPayload);\n        assertEquals(secondPayload, secondTopicListener.theStringEvent.getPayload());\n        assertNotEquals(secondPayload, firstTopicListener.theStringPayload);\n        assertNotEquals(secondPayload, firstTopicListener.theStringEvent.getPayload());\n    }\n\n    @Test\n    public void testSubscribeAndPublishWithTopic() {\n        String topic = \"/news\";\n        String payload = \"Hello World\";\n        TopicStringListener stringListener = new TopicStringListener();\n\n        sessionEventBus.subscribe(stringListener, topic);\n        sessionEventBus.publish(topic, this, payload);\n        assertEquals(payload, stringListener.theStringEvent.getPayload());\n    }\n\n    @Test\n    public void testSubscribeAndPublishWithDifferentTopic() {\n        String topic = \"/news\";\n        String payload = \"Hello World\";\n        String differentTopic = payload + \".extension\";\n        TopicStringListener stringListener = new TopicStringListener();\n\n        sessionEventBus.subscribe(stringListener, topic);\n        sessionEventBus.publish(differentTopic, this, payload);\n        assertNull(stringListener.theStringEvent);\n    }\n\n    @Test\n    public void testSubscribeAndPublishWithSameTopicButDifferentPayloadType() {\n        String topic = \"/news\";\n        Integer payload = 0;\n        TopicStringListener stringListener = new TopicStringListener();\n\n        sessionEventBus.subscribe(stringListener, topic);\n        sessionEventBus.publish(topic, this, payload);\n        assertNull(stringListener.theStringEvent);\n    }\n\n    @Test\n    public void testSubscribeTwoTopicListenersForSameTopicWithDifferentPayloadType() {\n        String topic = \"/news\";\n        String stringPayload = \"Hello World\";\n        Integer integerPayload = 0;\n        TopicStringListener stringListener = new TopicStringListener();\n        TopicIntegerListener integerListener = new TopicIntegerListener();\n\n        sessionEventBus.subscribe(stringListener, topic);\n        sessionEventBus.subscribe(integerListener, topic);\n\n        sessionEventBus.publish(topic, this, integerPayload);\n        assertNotNull(integerListener.theIntegerEvent);\n        assertNull(stringListener.theStringEvent);\n\n        sessionEventBus.publish(topic, this, stringPayload);\n        assertNotNull(integerListener.theIntegerEvent);\n        assertNotNull(stringListener.theStringEvent);\n    }\n\n    @Test\n    public void testSubscribeAndPublishWithListenerMethodsAndTooFewParameters() {\n        assertThrows(IllegalArgumentException.class, () -> sessionEventBus.subscribe(new InvalidListener1()));\n    }\n\n    @Test\n    public void testSubscribeAndPublishWithListenerMethodsAndTooManyParameters() {\n        assertThrows(IllegalArgumentException.class, () -> sessionEventBus.subscribe(new InvalidListener2()));\n    }\n\n    @Test\n    public void testPublishToInvalidScope() {\n        assertThrows(UnsupportedOperationException.class, () -> applicationEventBus.publish(EventScope.SESSION, this, \"fail\"));\n    }\n\n    @Test\n    @SuppressWarnings({\"unchecked\", \"rawtypes\"})\n    public void testPublishToParentScope() {\n        StringListener stringListener = mock(StringListener.class);\n\n        applicationEventBus.subscribe(stringListener);\n        sessionEventBus.publish(EventScope.APPLICATION, this, \"Hello World\");\n\n        ArgumentCaptor<Event> event = ArgumentCaptor.forClass(Event.class);\n        verify(stringListener).onEvent(event.capture());\n        assertEquals(\"Hello World\", event.getValue().getPayload());\n    }\n\n    @Test\n    public void testPublishToParentScopeWithListenerMethods() {\n        MultipleListeners listener = new MultipleListeners();\n\n        applicationEventBus.subscribe(listener);\n        sessionEventBus.publish(EventScope.APPLICATION, this, \"Hello World\");\n\n        assertNull(listener.theIntegerEvent);\n        assertNull(listener.theIntegerPayload);\n        assertNotNull(listener.theStringEvent);\n        assertEquals(\"Hello World\", listener.theStringEvent.getPayload());\n        assertEquals(\"Hello World\", listener.theStringPayload);\n    }\n\n    @Test\n    @SuppressWarnings({\"unchecked\", \"rawtypes\"})\n    public void testPropagateToChild() {\n        StringListener stringListener = mock(StringListener.class);\n\n        sessionEventBus.subscribe(stringListener);\n        applicationEventBus.publish(this, \"Hello World\");\n\n        ArgumentCaptor<Event> event = ArgumentCaptor.forClass(Event.class);\n        verify(stringListener).onEvent(event.capture());\n        assertEquals(\"Hello World\", event.getValue().getPayload());\n    }\n\n    @Test\n    public void testPropagateToChildWithListenerMethods() {\n        MultipleListeners listener = new MultipleListeners();\n\n        applicationEventBus.subscribe(listener);\n        applicationEventBus.publish(this, \"Hello World\");\n\n        assertNull(listener.theIntegerEvent);\n        assertNull(listener.theIntegerPayload);\n        assertNotNull(listener.theStringEvent);\n        assertEquals(\"Hello World\", listener.theStringEvent.getPayload());\n        assertEquals(\"Hello World\", listener.theStringPayload);\n    }\n\n    @Test\n    @SuppressWarnings({\"unchecked\", \"rawtypes\"})\n    public void testNoPropagationToChild() {\n        StringListener stringListener = mock(StringListener.class);\n\n        sessionEventBus.subscribe(stringListener, false);\n        applicationEventBus.publish(this, \"Hello World\");\n        sessionEventBus.publish(this, \"Hello World\");\n\n        ArgumentCaptor<Event> event = ArgumentCaptor.forClass(Event.class);\n        verify(stringListener, only()).onEvent(event.capture());\n        verifyNoMoreInteractions(stringListener);\n        assertEquals(\"Hello World\", event.getValue().getPayload());\n    }\n\n    @Test\n    public void testNoPropagationToChildWithListenerMethods() {\n        MultipleListeners listener = new MultipleListeners();\n\n        sessionEventBus.subscribe(listener, false);\n        sessionEventBus.publish(this, \"Hello World Session\");\n        applicationEventBus.publish(this, \"Hello World Application\");\n\n        assertNull(listener.theIntegerEvent);\n        assertNull(listener.theIntegerPayload);\n        assertNotNull(listener.theStringEvent);\n        assertEquals(\"Hello World Session\", listener.theStringEvent.getPayload());\n        assertEquals(\"Hello World Session\", listener.theStringPayload);\n    }\n\n    @Test\n    public void testSubscribeWithWeakReference() {\n        StringListener listener = new StringListener() {\n            int cnt = 0;\n\n            @Override\n            public void onEvent(Event<String> event) {\n                cnt++;\n                if (cnt > 1) {\n                    fail(\"I should have been garbage collected by now\");\n                }\n            }\n        };\n        applicationEventBus.subscribeWithWeakReference(listener);\n        applicationEventBus.publish(this, \"Hello World Application\");\n        listener = null;\n        System.gc();\n        applicationEventBus.publish(this, \"Hello World Application\");\n    }\n}\n"
  },
  {
    "path": "eventbus/src/test/java/org/vaadin/spring/events/support/ApplicationContextEventBrokerTest.java",
    "content": "/*\n * Copyright 2015 The original authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.vaadin.spring.events.support;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.context.ApplicationEvent;\nimport org.vaadin.spring.events.EventBus;\n\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\n\n/**\n * Test case for {@link org.vaadin.spring.events.support.ApplicationContextEventBroker}.\n *\n * @author Petter Holmström (petter@vaadin.com)\n */\npublic class ApplicationContextEventBrokerTest {\n\n    @Test\n    public void testOnApplicationEvent() {\n        ApplicationEvent event = new ApplicationEvent(this) {\n\n            private static final long serialVersionUID = 7475015652750718692L;\n\n            @Override\n            public Object getSource() {\n                return \"mySource\";\n            }\n        };\n        EventBus eventBus = mock(EventBus.class);\n        new ApplicationContextEventBroker(eventBus).onApplicationEvent(event);\n        verify(eventBus).publish(\"mySource\", event);\n    }\n\n}\n"
  },
  {
    "path": "pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>org.vaadin.spring</groupId>\n    <artifactId>parent-pom</artifactId>\n    <version>14.0.1-SNAPSHOT</version>\n    <packaging>pom</packaging>\n\n    <name>Vaadin4Spring</name>\n    <description>\n        Additions to the official Vaadin Spring add-on.\n    </description>\n    <url>https://github.com/peholmst/vaadin4spring</url>\n\n    <licenses>\n        <license>\n            <name>Apache License 2.0</name>\n            <url>http://www.apache.org/licenses/LICENSE-2.0.html</url>\n        </license>\n    </licenses>\n\n    <scm>\n        <url>https://github.com/peholmst/vaadin4spring</url>\n        <connection>scm:git:git@github.com:peholmst/vaadin4spring.git</connection>\n        <developerConnection>scm:git:git@github.com:peholmst/vaadin4spring.git</developerConnection>\n        <tag>HEAD</tag>\n    </scm>\n\n    <distributionManagement>\n        <snapshotRepository>\n            <id>sonatype-nexus-snapshots</id>\n            <url>https://oss.sonatype.org/content/repositories/snapshots</url>\n        </snapshotRepository>\n        <repository>\n            <id>sonatype-nexus-staging</id>\n            <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>\n        </repository>\n    </distributionManagement>\n\n    <developers>\n        <!-- In alphabetical order -->\n        <developer>\n            <name>Chris Phillipson</name>\n            <email>fastnsilver@gmail.com</email>\n        </developer>\n        <developer>\n            <name>Erik Lumme</name>\n            <organization>Vaadin</organization>\n            <email>erik@vaadin.com</email>\n        </developer>\n        <developer>\n            <name>Gert-Jan Timmer</name>\n            <email>gjr.timmer@gmail.com</email>\n        </developer>\n        <developer>\n            <name>Idel Pivnitskiy</name>\n            <email>idel.pivnitskiy@gmail.com</email>\n        </developer>\n        <developer>\n            <name>Josh Long</name>\n            <email>josh@joshlong.com</email>\n        </developer>\n        <developer>\n            <name>Marco Luthardt</name>\n            <email>marco.luthardt@iandme.net</email>\n        </developer>\n        <developer>\n            <name>Matti Tahvonen</name>\n            <organization>Vaadin</organization>\n            <email>matti@vaadin.com</email>\n        </developer>\n        <developer>\n            <name>Nicolas Frankel</name>\n            <email>nicolas@frankel.ch</email>\n        </developer>\n        <developer>\n            <name>Peter Lehto</name>\n            <organization>Vaadin</organization>\n            <email>peter@vaadin.com</email>\n        </developer>\n        <developer>\n            <name>Petter Holmström</name>\n            <organization>Vaadin</organization>\n            <email>petter@vaadin.com</email>\n        </developer>\n        <developer>\n            <name>Tobias Placht</name>\n            <email>dev@knacht.net</email>\n        </developer>\n    </developers>\n\n    <properties>\n        <project.build.encoding>UTF-8</project.build.encoding>\n        <project.build.target>1.8</project.build.target>\n        <project.build.source>1.8</project.build.source>\n\n        <vaadin.version>14.0.1</vaadin.version>\n\n        <!-- Match version used by Vaadin Spring dependency -->\n        <spring.version>5.1.2.RELEASE</spring.version>\n\n        <junit-jupiter.version>5.5.1</junit-jupiter.version>\n        <mockito.version>3.0.0</mockito.version>\n    </properties>\n\n    <dependencyManagement>\n        <dependencies>\n            <dependency>\n                <groupId>com.vaadin</groupId>\n                <artifactId>vaadin-bom</artifactId>\n                <version>${vaadin.version}</version>\n                <type>pom</type>\n                <scope>import</scope>\n            </dependency>\n\n            <dependency>\n                <groupId>org.mockito</groupId>\n                <artifactId>mockito-core</artifactId>\n                <version>${mockito.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.junit.jupiter</groupId>\n                <artifactId>junit-jupiter-engine</artifactId>\n                <version>${junit-jupiter.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.springframework</groupId>\n                <artifactId>spring-test</artifactId>\n                <version>${spring.version}</version>\n            </dependency>\n        </dependencies>\n    </dependencyManagement>\n\n    <build>\n        <pluginManagement>\n            <plugins>\n                <plugin>\n                    <groupId>org.apache.maven.plugins</groupId>\n                    <artifactId>maven-compiler-plugin</artifactId>\n                    <version>3.8.1</version>\n                    <configuration>\n                        <encoding>${project.build.encoding}</encoding>\n                        <target>${project.build.target}</target>\n                        <source>${project.build.source}</source>\n                    </configuration>\n                </plugin>\n                <plugin>\n                    <groupId>org.apache.maven.plugins</groupId>\n                    <artifactId>maven-resources-plugin</artifactId>\n                    <version>3.1.0</version>\n                    <configuration>\n                        <encoding>${project.build.encoding}</encoding>\n                    </configuration>\n                </plugin>\n                <plugin>\n                    <groupId>org.apache.maven.plugins</groupId>\n                    <artifactId>maven-deploy-plugin</artifactId>\n                    <version>2.8.2</version>\n                </plugin>\n                <plugin>\n                    <groupId>org.apache.maven.plugins</groupId>\n                    <artifactId>maven-surefire-plugin</artifactId>\n                    <version>3.0.0-M3</version>\n                </plugin>\n                <plugin>\n                    <groupId>org.apache.maven.plugins</groupId>\n                    <artifactId>maven-release-plugin</artifactId>\n                    <version>2.5.3</version>\n                    <configuration>\n                        <tagNameFormat>v@{project.version}</tagNameFormat>\n                        <autoVersionSubmodules>true</autoVersionSubmodules>\n                        <releaseProfiles>release</releaseProfiles>\n                    </configuration>\n                </plugin>\n            </plugins>\n        </pluginManagement>\n    </build>\n\n    <profiles>\n        <profile>\n            <id>release</id>\n            <build>\n                <plugins>\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-source-plugin</artifactId>\n                        <version>3.1.0</version>\n                        <executions>\n                            <execution>\n                                <id>attach-sources</id>\n                                <phase>verify</phase>\n                                <goals>\n                                    <goal>jar-no-fork</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-javadoc-plugin</artifactId>\n                        <version>3.1.1</version>\n                        <executions>\n                            <execution>\n                                <id>attach-javadocs</id>\n                                <goals>\n                                    <goal>jar</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                        <configuration>\n                            <links>\n                                <link>http://docs.spring.io/spring/docs/${spring.version}/javadoc-api/</link>\n                                <link>https://vaadin.com/api/platform/${vaadin.version}/</link>\n                            </links>\n                            <additionalparam>-Xdoclint:none</additionalparam>\n                            <encoding>UTF-8</encoding>\n                        </configuration>\n                    </plugin>\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-gpg-plugin</artifactId>\n                        <version>1.5</version>\n                        <executions>\n                            <execution>\n                                <id>sign-artifacts</id>\n                                <phase>verify</phase>\n                                <goals>\n                                    <goal>sign</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n                </plugins>\n            </build>\n        </profile>\n    </profiles>\n\n    <modules>\n        <module>eventbus</module>\n    </modules>\n</project>\n"
  }
]