This is an automated email from the ASF dual-hosted git repository. reiern70 pushed a commit to branch WICKET-6930-websocket-improvements in repository https://gitbox.apache.org/repos/asf/wicket.git
commit c48a23a903426eb329b45a690a464fde751b1405 Author: reiern70 <[email protected]> AuthorDate: Sun Nov 7 11:38:39 2021 +0300 WICKET-6930: pass page class as a kind of context --- .../examples/websocket/JSR356Application.java | 11 +++- .../wicket/examples/websocket/JSR356Session.java | 51 +++++++++++++++++ .../WebSocketPushUpdateProgressDemoPage.java | 3 +- .../websocket/progress/ProgressBarTogglePanel.java | 36 ++++-------- .../websocket/progress/ProgressUpdater.java | 36 ++++++------ .../ws/api/AbstractWebSocketConnection.java | 2 +- .../ws/api/AbstractWebSocketProcessor.java | 25 +++++--- .../protocol/ws/api/BaseWebSocketBehavior.java | 2 + .../protocol/ws/api/WebSocketPushBroadcaster.java | 66 ++++++++++++++++++++++ .../api/registry/IWebSocketConnectionRegistry.java | 25 +++++++- .../wicket/protocol/ws/api/registry/PageIdKey.java | 24 ++++++++ .../SimpleWebSocketConnectionRegistry.java | 26 +++++++++ .../ws/api/res/js/wicket-websocket-jquery.js | 1 + .../ws/api/res/js/wicket-websocket-setup.js.tmpl | 2 +- .../ws/util/tester/TestWebSocketProcessor.java | 1 + .../util/tester/WebSocketTesterBehaviorTest.java | 2 +- .../ws/javax/JavaxWebSocketConnection.java | 2 +- .../wicket/protocol/ws/javax/WicketEndpoint.java | 2 + 18 files changed, 259 insertions(+), 58 deletions(-) diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Application.java b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Application.java index 98a9779..e178f7c 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Application.java +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Application.java @@ -16,12 +16,15 @@ */ package org.apache.wicket.examples.websocket; +import org.apache.wicket.Session; import org.apache.wicket.examples.WicketExampleApplication; import org.apache.wicket.examples.websocket.charts.ChartWebSocketResource; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.protocol.https.HttpsConfig; import org.apache.wicket.protocol.https.HttpsMapper; import org.apache.wicket.protocol.ws.WebSocketSettings; +import org.apache.wicket.request.Request; +import org.apache.wicket.request.Response; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -70,7 +73,13 @@ public class JSR356Application extends WicketExampleApplication getCspSettings().blocking().disabled(); } - @Override + @Override + public Session newSession(Request request, Response response) + { + return new JSR356Session(request); + } + + @Override protected void onDestroy() { scheduledExecutorService.shutdownNow(); diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Session.java b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Session.java new file mode 100644 index 0000000..e45ecde --- /dev/null +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/JSR356Session.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.wicket.examples.websocket; + + +import java.util.concurrent.ScheduledExecutorService; + +import org.apache.wicket.examples.websocket.progress.ProgressUpdater; +import org.apache.wicket.protocol.http.WebSession; +import org.apache.wicket.request.Request; + +public class JSR356Session extends WebSession { + + + private ProgressUpdater.ProgressUpdateTask progressUpdateTask; + + public JSR356Session(Request request) { + super(request); + } + + public ProgressUpdater.ProgressUpdateTask getProgressUpdateTask() { + return progressUpdateTask; + } + + public synchronized void startTask() { + if (progressUpdateTask != null && progressUpdateTask.isRunning()) { + return; + } + ScheduledExecutorService service = JSR356Application.get().getScheduledExecutorService(); + progressUpdateTask = ProgressUpdater.start(getApplication(), getId(), service); + } + + public static JSR356Session getInstance() { + return (JSR356Session)get(); + } +} diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketPushUpdateProgressDemoPage.java b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketPushUpdateProgressDemoPage.java index 01d16b2..bbf923d 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketPushUpdateProgressDemoPage.java +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/WebSocketPushUpdateProgressDemoPage.java @@ -18,10 +18,11 @@ package org.apache.wicket.examples.websocket; import org.apache.wicket.examples.WicketExamplePage; import org.apache.wicket.examples.websocket.progress.ProgressBarTogglePanel; +import org.apache.wicket.examples.websocket.progress.ProgressUpdater; import org.apache.wicket.protocol.https.RequireHttps; @RequireHttps -public class WebSocketPushUpdateProgressDemoPage extends WicketExamplePage +public class WebSocketPushUpdateProgressDemoPage extends WicketExamplePage implements ProgressUpdater.ITaskProgressListener { public WebSocketPushUpdateProgressDemoPage() { diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressBarTogglePanel.java b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressBarTogglePanel.java index 03e7733..71e389c 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressBarTogglePanel.java +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressBarTogglePanel.java @@ -22,6 +22,7 @@ import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.event.IEvent; import org.apache.wicket.examples.websocket.JSR356Application; +import org.apache.wicket.examples.websocket.JSR356Session; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.IModel; @@ -34,7 +35,7 @@ public class ProgressBarTogglePanel extends Panel private int progress = 0; private boolean showProgress = true; - private ProgressUpdater.ProgressUpdateTask progressUpdateTask; + public ProgressBarTogglePanel(String id) { @@ -46,7 +47,7 @@ public class ProgressBarTogglePanel extends Panel { @Override protected void onConnect(ConnectedMessage message) { - progressUpdateTask = ProgressBarTogglePanel.startProgressTask(message); + } }); @@ -65,33 +66,25 @@ public class ProgressBarTogglePanel extends Panel @Override public void onClick(AjaxRequestTarget target) { - if (progressUpdateTask.isRunning() && !progressUpdateTask.isCanceled()) + ProgressUpdater.ProgressUpdateTask progressUpdateTask = JSR356Session.getInstance().getProgressUpdateTask(); + if (progressUpdateTask != null && progressUpdateTask.isRunning() && !progressUpdateTask.isCanceled()) { progressUpdateTask.cancel(); } else { - ScheduledExecutorService service = JSR356Application.get().getScheduledExecutorService(); - ProgressUpdater.restart(progressUpdateTask, service); + JSR356Session.getInstance().startTask(); } target.add(ProgressBarTogglePanel.this); } - }.setBody(new IModel<String>() - { - @Override - public String getObject() - { - return progressUpdateTask != null && progressUpdateTask.isRunning() && !progressUpdateTask.isCanceled() ? "Cancel task" : "Restart task"; - } + }.setBody((IModel<String>) () -> { + ProgressUpdater.ProgressUpdateTask progressUpdateTask = JSR356Session.getInstance().getProgressUpdateTask(); + return progressUpdateTask != null && progressUpdateTask.isRunning() && !progressUpdateTask.isCanceled() ? "Cancel task" : "Restart task"; })); - add(new Label("progressBar", new IModel<String>() - { - @Override - public String getObject() - { - return progressUpdateTask != null && progressUpdateTask.isRunning() ? "Background Task is " + progress + "% completed" : "No task is running"; - } + add(new Label("progressBar", (IModel<String>) () -> { + ProgressUpdater.ProgressUpdateTask progressUpdateTask = JSR356Session.getInstance().getProgressUpdateTask(); + return progressUpdateTask != null && progressUpdateTask.isRunning() ? "Background Task is " + progress + "% completed" : "No task is running"; }) { @Override @@ -103,11 +96,6 @@ public class ProgressBarTogglePanel extends Panel }); } - public static ProgressUpdater.ProgressUpdateTask startProgressTask(ConnectedMessage message) - { - ScheduledExecutorService service = JSR356Application.get().getScheduledExecutorService(); - return ProgressUpdater.start(message, service); - } @Override public void onEvent(IEvent<?> event) diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressUpdater.java b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressUpdater.java index 60a3e94..aa928cb 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressUpdater.java +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/websocket/progress/ProgressUpdater.java @@ -28,6 +28,7 @@ import org.apache.wicket.protocol.ws.api.message.ConnectedMessage; import org.apache.wicket.protocol.ws.api.message.IWebSocketPushMessage; import org.apache.wicket.protocol.ws.api.registry.IKey; import org.apache.wicket.protocol.ws.api.registry.IWebSocketConnectionRegistry; +import org.apache.wicket.protocol.ws.api.registry.PageIdKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,20 +37,23 @@ import org.slf4j.LoggerFactory; */ public class ProgressUpdater { + /** + * Marks a page as listening to task progress. + */ + public interface ITaskProgressListener { + + } + private static final Logger LOGGER = LoggerFactory.getLogger(ProgressUpdater.class); - public static ProgressUpdateTask start(ConnectedMessage message, ScheduledExecutorService scheduledExecutorService) + public static ProgressUpdateTask start(Application application, String session, ScheduledExecutorService scheduledExecutorService) { // create an asynchronous task that will write the data to the client - ProgressUpdateTask progressUpdateTask = new ProgressUpdateTask(message.getApplication(), message.getSessionId(), message.getKey()); + ProgressUpdateTask progressUpdateTask = new ProgressUpdateTask(application, session); scheduledExecutorService.schedule(progressUpdateTask, 1, TimeUnit.SECONDS); return progressUpdateTask; } - public static void restart(ProgressUpdateTask progressUpdateTask, ScheduledExecutorService scheduledExecutorService) { - scheduledExecutorService.schedule(progressUpdateTask, 1, TimeUnit.SECONDS); - } - /** * A push message used to update progress. */ @@ -80,16 +84,14 @@ public class ProgressUpdater */ private final String applicationName; private final String sessionId; - private final IKey key; private boolean canceled = false; private boolean running = false; - private ProgressUpdateTask(Application application, String sessionId, IKey key) + private ProgressUpdateTask(Application application, String sessionId) { this.applicationName = application.getName(); this.sessionId = sessionId; - this.key = key; } @Override @@ -98,22 +100,13 @@ public class ProgressUpdater running = true; Application application = Application.get(applicationName); WebSocketSettings webSocketSettings = WebSocketSettings.Holder.get(application); - IWebSocketConnectionRegistry webSocketConnectionRegistry = webSocketSettings.getConnectionRegistry(); int progress = 0; while (progress <= 100) { - IWebSocketConnection connection = webSocketConnectionRegistry.getConnection(application, sessionId, key); try { - if (connection == null || !connection.isOpen()) - { - running = false; - // stop if the web socket connection is closed - return; - } - if (canceled) { canceled = false; @@ -123,7 +116,12 @@ public class ProgressUpdater WebSocketPushBroadcaster broadcaster = new WebSocketPushBroadcaster(webSocketSettings.getConnectionRegistry()); - broadcaster.broadcast(new ConnectedMessage(application, sessionId, key), new ProgressUpdate(progress)); + broadcaster.broadcastAllMatchingFilter(application, new IWebSocketConnectionRegistry.IConnectionsFilter() { + @Override + public boolean acceptConnection(String sessionId, IKey key) { + return ProgressUpdateTask.this.sessionId.equals(sessionId) && key instanceof PageIdKey && ITaskProgressListener.class.isAssignableFrom(((PageIdKey) key).getPageClass()); + } + }, new ProgressUpdate(progress)); // sleep for a while to simulate work TimeUnit.SECONDS.sleep(1); diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketConnection.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketConnection.java index 8726d56..3cd0f62 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketConnection.java +++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketConnection.java @@ -50,7 +50,7 @@ public abstract class AbstractWebSocketConnection implements IWebSocketConnectio @Override public void sendMessage(IWebSocketPushMessage message) { - webSocketProcessor.broadcastMessage(message); + webSocketProcessor.broadcastMessage(message, this); } @Override diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java index 82cd21a..d6d35b0 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java +++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java @@ -81,9 +81,11 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor * A pageId indicating that the endpoint is WebSocketResource */ static final int NO_PAGE_ID = -1; + static final String NO_PAGE_CLASS = "_NO_PAGE"; private final WebRequest webRequest; private final int pageId; + private final String pageClass; private final String resourceName; private final String connectionToken; private final Url baseUrl; @@ -112,6 +114,7 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor } this.sessionId = httpSession.getId(); String pageId = request.getParameter("pageId"); + String pageClass = request.getParameter("pageClass"); this.resourceName = request.getParameter("resourceName"); this.connectionToken = request.getParameter("connectionToken"); if (Strings.isEmpty(pageId) && Strings.isEmpty(resourceName)) @@ -121,10 +124,12 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor if (Strings.isEmpty(pageId) == false) { this.pageId = Integer.parseInt(pageId, 10); + this.pageClass = pageClass; } else { this.pageId = NO_PAGE_ID; + this.pageClass = NO_PAGE_CLASS; } String baseUrl = request.getParameter(WebRequest.PARAM_AJAX_BASE_URL); @@ -181,7 +186,7 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor } } - broadcastMessage(new ConnectedMessage(getApplication(), getSessionId(), key)); + broadcastMessage(new ConnectedMessage(getApplication(), getSessionId(), key), connection); } @Override @@ -203,6 +208,13 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor } } + public final void broadcastMessage(final IWebSocketMessage message) + { + IKey key = getRegistryKey(); + IWebSocketConnection connection = connectionRegistry.getConnection(application, sessionId, key); + broadcastMessage(message, connection); + } + /** * Exports the Wicket thread locals and broadcasts the received message from the client to all * interested components and behaviors in the page with id {@code #pageId} @@ -215,11 +227,8 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor * @param message * the message to broadcast */ - public final void broadcastMessage(final IWebSocketMessage message) + public final void broadcastMessage(final IWebSocketMessage message, IWebSocketConnection connection) { - IKey key = getRegistryKey(); - IWebSocketConnection connection = connectionRegistry.getConnection(application, sessionId, key); - if (connection != null && (connection.isOpen() || isSpecialMessage(message))) { Application oldApplication = ThreadContext.getApplication(); @@ -249,8 +258,8 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor if (session == null) { - connectionRegistry.removeConnection(application, sessionId, key); - LOG.debug("No Session could be found for session id '{}' and key '{}'!", sessionId, key); + connectionRegistry.removeConnection(application, sessionId, connection.getKey()); + LOG.debug("No Session could be found for session id '{}' and key '{}'!", sessionId, connection.getKey()); return; } @@ -399,7 +408,7 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor IKey key; if (Strings.isEmpty(resourceName)) { - key = new PageIdKey(pageId); + key = new PageIdKey(pageId, pageClass); } else { diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/BaseWebSocketBehavior.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/BaseWebSocketBehavior.java index c0a1f18..7ff8d80 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/BaseWebSocketBehavior.java +++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/BaseWebSocketBehavior.java @@ -128,6 +128,7 @@ public class BaseWebSocketBehavior extends Behavior { int pageId = component.getPage().getPageId(); variables.put("pageId", pageId); + variables.put("pageClass", component.getPage().getClass().getName()); variables.put("resourceName", ""); variables.put("connectionToken", ""); } @@ -136,6 +137,7 @@ public class BaseWebSocketBehavior extends Behavior variables.put("resourceName", resourceName); variables.put("connectionToken", connectionToken); variables.put("pageId", false); + variables.put("pageClass", ""); } WebSocketSettings webSocketSettings = WebSocketSettings.Holder.get(component.getApplication()); diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketPushBroadcaster.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketPushBroadcaster.java index db653d2..fc37a7f 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketPushBroadcaster.java +++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketPushBroadcaster.java @@ -109,6 +109,72 @@ public class WebSocketPushBroadcaster process(application, wsConnections, message); } + /** + * Processes the given message in all pages in a given session that have active Web Socket connections. + * The message is sent as an event to the Page and components of the session allowing the components + * to be updated. + * + * This method can be invoked from any thread, even a non-wicket thread. By default all processing + * is done in the caller thread. Use + * {@link WebSocketSettings#setWebSocketPushMessageExecutor(org.apache.wicket.protocol.ws.concurrent.Executor)} + * to move processing to background threads. + * + * If some connections are not in valid state they are silently ignored. + * + * @param application + * The wicket application + * + * @param sessionId + * The session ID + * @param message + * The push message event + */ + public void broadcastAllInSession(Application application, String sessionId, IWebSocketPushMessage message) + { + Args.notNull(application, "application"); + Args.notNull(message, "message"); + + Collection<IWebSocketConnection> wsConnections = registry.getConnections(application, sessionId); + if (wsConnections == null) + { + return; + } + process(application, wsConnections, message); + } + + /** + * Processes the given message in all pages in a given session that have active Web Socket connections and match + * the given filter. The message is sent as an event to the Page and components of the session allowing the components + * to be updated. + * + * This method can be invoked from any thread, even a non-wicket thread. By default all processing + * is done in the caller thread. Use + * {@link WebSocketSettings#setWebSocketPushMessageExecutor(org.apache.wicket.protocol.ws.concurrent.Executor)} + * to move processing to background threads. + * + * If some connections are not in valid state they are silently ignored. + * + * @param application + * The wicket application + * + * @param connectionsFilter + * the {@link org.apache.wicket.protocol.ws.api.registry.IWebSocketConnectionRegistry.IConnectionsFilter} + * @param message + * The push message event + */ + public void broadcastAllMatchingFilter(Application application, IWebSocketConnectionRegistry.IConnectionsFilter connectionsFilter, IWebSocketPushMessage message) + { + Args.notNull(application, "application"); + Args.notNull(message, "message"); + + Collection<IWebSocketConnection> wsConnections = registry.getConnections(application, connectionsFilter); + if (wsConnections == null) + { + return; + } + process(application, wsConnections, message); + } + private void process(final Application application, final Collection<IWebSocketConnection> wsConnections, final IWebSocketPushMessage message) { diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/IWebSocketConnectionRegistry.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/IWebSocketConnectionRegistry.java index 2782a93..c4de9a5 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/IWebSocketConnectionRegistry.java +++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/IWebSocketConnectionRegistry.java @@ -29,6 +29,17 @@ import org.apache.wicket.protocol.ws.api.IWebSocketConnection; public interface IWebSocketConnectionRegistry { /** + * Interface allowing to filter web-sockets connection. This could be used for use cases like the + * following: you + */ + interface IConnectionsFilter + { + + boolean acceptConnection(String sessionId, IKey key); + + } + + /** * @param application * the web application to look in * @param sessionId @@ -44,12 +55,24 @@ public interface IWebSocketConnectionRegistry * the web application to look in * @param sessionId * the http session id - * @return collection of web socket connection used by a client with the given session id + * @return collection of web socket connections used by a client with the given session id */ Collection<IWebSocketConnection> getConnections(Application application, String sessionId); /** + * + * @param application + * the web application to look in + * @param connectionsFilter + * the {@link org.apache.wicket.protocol.ws.api.registry.IWebSocketConnectionRegistry.IConnectionsFilter} + * + * @return collection of web socket connections that match certain filter + */ + Collection<IWebSocketConnection> getConnections(Application application, IConnectionsFilter connectionsFilter); + + + /** * @param application * the web application to look in * @return collection of web socket connection used by any client connected to specified application diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/PageIdKey.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/PageIdKey.java index 84eee23..ba50ed2 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/PageIdKey.java +++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/PageIdKey.java @@ -16,6 +16,9 @@ */ package org.apache.wicket.protocol.ws.api.registry; +import org.apache.wicket.Session; +import org.apache.wicket.WicketRuntimeException; +import org.apache.wicket.page.IManageablePage; import org.apache.wicket.util.lang.Args; /** @@ -25,9 +28,30 @@ public class PageIdKey implements IKey { private final Integer pageId; + private Class<? extends IManageablePage> pageClass; + public PageIdKey(Integer pageId) { + this(pageId, null); + } + + public PageIdKey(Integer pageId, String pageClass) + { this.pageId = Args.notNull(pageId, "pageId"); + Args.notNull(pageClass, "pageClass"); + try { + this.pageClass = (Class<IManageablePage>)Thread.currentThread().getContextClassLoader().loadClass(pageClass); + } catch (ClassNotFoundException e) { + //throw new WicketRuntimeException(e); + } + } + + /** + * @return returns the page class. + */ + public Class<? extends IManageablePage> getPageClass() + { + return pageClass; } @Override diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/SimpleWebSocketConnectionRegistry.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/SimpleWebSocketConnectionRegistry.java index b5005aa..e176a15 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/SimpleWebSocketConnectionRegistry.java +++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/registry/SimpleWebSocketConnectionRegistry.java @@ -19,6 +19,7 @@ package org.apache.wicket.protocol.ws.api.registry; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Map; import java.util.concurrent.ConcurrentMap; import org.apache.wicket.Application; @@ -79,6 +80,31 @@ public class SimpleWebSocketConnectionRegistry implements IWebSocketConnectionRe return connections; } + @Override + public Collection<IWebSocketConnection> getConnections(Application application, IConnectionsFilter connectionsFilter) + { + Args.notNull(application, "application"); + Args.notNull(connectionsFilter, "connectionsFilter"); + + Collection<IWebSocketConnection> connections = new ArrayList<>(); + ConcurrentMap<String, ConcurrentMap<IKey, IWebSocketConnection>> connectionsBySession = application.getMetaData(KEY); + if (connectionsBySession != null) + { + for (Map.Entry<String, ConcurrentMap<IKey, IWebSocketConnection>> connectionsByPage : connectionsBySession.entrySet()) + { + for (Map.Entry<IKey, IWebSocketConnection> connectionEntry: connectionsByPage.getValue().entrySet()) + { + if (connectionsFilter.acceptConnection(connectionsByPage.getKey(), connectionEntry.getKey())) + { + connections.add(connectionEntry.getValue()); + } + } + + } + } + return connections; + } + /** * Returns a collection of currently active websockets. The connections might close at any time. * diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-jquery.js b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-jquery.js index cd06ad5..e398207 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-jquery.js +++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-jquery.js @@ -74,6 +74,7 @@ if (WWS.pageId !== false) { url += '?pageId=' + encodeURIComponent(WWS.pageId); + url += '&pageClass=' + encodeURIComponent(WWS.pageClass); } else if (WWS.resourceName) { url += '?resourceName=' + encodeURIComponent(WWS.resourceName); if (WWS.connectionToken) { diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-setup.js.tmpl b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-setup.js.tmpl index 1533cbf..b73eb01 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-setup.js.tmpl +++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-setup.js.tmpl @@ -2,7 +2,7 @@ 'use strict'; if (typeof(Wicket.WebSocket.appName) === "undefined") { - jQuery.extend(Wicket.WebSocket, { pageId: ${pageId}, resourceName: '${resourceName}', connectionToken: '${connectionToken}', + jQuery.extend(Wicket.WebSocket, { pageId: ${pageId}, pageClass: '${pageClass}', resourceName: '${resourceName}', connectionToken: '${connectionToken}', baseUrl: '${baseUrl}', contextPath: '${contextPath}', appName: '${applicationName}', port: ${port}, securePort: ${securePort}, filterPrefix: '${filterPrefix}', sessionId: '${sessionId}' }); Wicket.WebSocket.createDefaultConnection(); diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketProcessor.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketProcessor.java index e48b908..6d6736d 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketProcessor.java +++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketProcessor.java @@ -84,6 +84,7 @@ abstract class TestWebSocketProcessor extends AbstractWebSocketProcessor Args.notNull(page, "page"); MockHttpServletRequest request = createRequest(wicketTester); request.addParameter("pageId", page.getId()); + request.addParameter("pageClass", page.getClass().getName()); return request; } diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterBehaviorTest.java b/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterBehaviorTest.java index 29ec707..912cec5 100644 --- a/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterBehaviorTest.java +++ b/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterBehaviorTest.java @@ -131,7 +131,7 @@ public class WebSocketTesterBehaviorTest } }; webSocketTester.broadcast(tester.getApplication(), tester.getHttpSession().getId(), - new PageIdKey(page.getPageId()), broadcastMessage); + new PageIdKey(page.getPageId(), page.getClass().getName()), broadcastMessage); assertTrue(messageReceived.get()); webSocketTester.destroy(); diff --git a/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketConnection.java b/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketConnection.java index 41fa304..f7e4ca4 100644 --- a/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketConnection.java +++ b/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketConnection.java @@ -49,7 +49,7 @@ public class JavaxWebSocketConnection extends AbstractWebSocketConnection public JavaxWebSocketConnection(Session session, AbstractWebSocketProcessor webSocketProcessor) { super(webSocketProcessor); - this.session = Args.notNull(session, "connection"); + this.session = Args.notNull(session, "session"); } @Override diff --git a/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/WicketEndpoint.java b/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/WicketEndpoint.java index 4808dbd..a73324b 100644 --- a/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/WicketEndpoint.java +++ b/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/WicketEndpoint.java @@ -47,6 +47,7 @@ public class WicketEndpoint extends Endpoint * The name of the request parameter that holds the application name */ private static final String WICKET_APP_PARAM_NAME = "wicket-app-name"; + private static final String WICKET_SESSION_ID = "jsessionid"; private final AtomicBoolean applicationDestroyed = new AtomicBoolean(false); @@ -56,6 +57,7 @@ public class WicketEndpoint extends Endpoint public void onOpen(Session session, EndpointConfig endpointConfig) { String appName = getApplicationName(session); + session.getId(); WebApplication app = (WebApplication) WebApplication.get(appName); app.getApplicationListeners().add(new ApplicationListener(applicationDestroyed));
