Skip to content

Commit c0f386b

Browse files
fix(web2): Fixed whiteboard services unregistration and context managing (#5737)
* fix in services unregistration wip * removed debug listener * fixed copyright plate * Fixed compilation issue * Add comment on gwt-maven-compiler requirements * now context names are changed on every creation * minor refactor * removed useless prototype scope * removed useless Bundle Scope for ResourceContext
1 parent b6a2b8f commit c0f386b

File tree

6 files changed

+113
-96
lines changed

6 files changed

+113
-96
lines changed

kura/org.eclipse.kura.rest.provider/src/main/java/org/eclipse/kura/internal/rest/auth/SessionRestService.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/*******************************************************************************
22
* Copyright (c) 2023, 2025 Eurotech and/or its affiliates and others
3-
*
3+
*
44
* This program and the accompanying materials are made
55
* available under the terms of the Eclipse Public License 2.0
66
* which is available at https://www.eclipse.org/legal/epl-2.0/
7-
*
7+
*
88
* SPDX-License-Identifier: EPL-2.0
9-
*
9+
*
1010
* Contributors:
1111
* Eurotech
1212
*******************************************************************************/
@@ -19,10 +19,6 @@
1919
import java.util.Optional;
2020
import java.util.Set;
2121

22-
import jakarta.servlet.http.HttpServletRequest;
23-
import jakarta.servlet.http.HttpServletResponse;
24-
import jakarta.servlet.http.HttpSession;
25-
2622
import org.eclipse.kura.audit.AuditConstants;
2723
import org.eclipse.kura.audit.AuditContext;
2824
import org.eclipse.kura.internal.rest.auth.dto.AuthenticationInfoDTO;
@@ -42,6 +38,9 @@
4238
import org.slf4j.Logger;
4339
import org.slf4j.LoggerFactory;
4440

41+
import jakarta.servlet.http.HttpServletRequest;
42+
import jakarta.servlet.http.HttpServletResponse;
43+
import jakarta.servlet.http.HttpSession;
4544
import jakarta.ws.rs.Consumes;
4645
import jakarta.ws.rs.GET;
4746
import jakarta.ws.rs.POST;

kura/org.eclipse.kura.web2/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@
134134
<style>OBF</style> <!-- DETAILED https://support.google.com/code/answer/55203?topic=10212 -->
135135
<failOnError>true</failOnError>
136136
<extraJvmArgs>-Xmx2048M -Xss1024k -XX:+UseParallelGC</extraJvmArgs>
137+
<!-- gwt-maven-plugin supports languages feature only up to java 11-->
137138
<sourceLevel>auto</sourceLevel>
138139
<localWorkers>2</localWorkers>
139140
<runTarget>denali.html</runTarget>

kura/org.eclipse.kura.web2/src/main/java/org/eclipse/kura/web/Console.java

Lines changed: 82 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@
8383
import org.osgi.service.event.Event;
8484
import org.osgi.service.event.EventAdmin;
8585
import org.osgi.service.event.EventProperties;
86-
import org.osgi.service.http.NamespaceException;
8786
import org.osgi.service.servlet.context.ServletContextHelper;
8887
import org.osgi.service.servlet.whiteboard.HttpWhiteboardConstants;
8988
import org.slf4j.Logger;
@@ -96,9 +95,8 @@
9695

9796
public class Console implements SelfConfiguringComponent {
9897

99-
private static final String SESSION_CONTEXT_NAME = "sessionContext";
100-
101-
private static final String RESOURCE_CONTEXT_NAME = "resourceContext";
98+
private static final String SESSION_CONTEXT_NAME_PREFIX = "sessionContext-";
99+
private static final String RESOURCE_CONTEXT_NAME_PREFIX = "resourceContext-";
102100

103101
private static final String SESSION = "/session";
104102

@@ -117,6 +115,8 @@ public class Console implements SelfConfiguringComponent {
117115
private static final String PASSWORD_AUTH_PATH = LOGIN_MODULE_PATH + "/password";
118116
private static final String CERT_AUTH_PATH = LOGIN_MODULE_PATH + "/cert";
119117

118+
private static final String XSRF_PATH = "/xsrf";
119+
120120
private static final Logger logger = LoggerFactory.getLogger(Console.class);
121121

122122
private String appRoot;
@@ -138,6 +138,9 @@ public class Console implements SelfConfiguringComponent {
138138
private final Set<ServiceRegistration<ResourcesService>> resources = new CopyOnWriteArraySet<>();
139139
private final Set<ServiceRegistration<Servlet>> servlets = new CopyOnWriteArraySet<>();
140140

141+
private final Set<String> authenticationPaths = new HashSet<>(
142+
Arrays.asList(AUTH_PATH, PASSWORD_AUTH_PATH, CERT_AUTH_PATH));
143+
141144
private BundleContext bundleContext;
142145

143146
private static Console instance;
@@ -268,14 +271,11 @@ private void doUpdate(ConsoleOptions options) {
268271
setAppRoot(options.getAppRoot());
269272
setSessionMaxInactiveInterval(options.getSessionMaxInactivityInterval());
270273

271-
try {
272-
initHTTPService();
273-
} catch (NamespaceException e) {
274-
logger.warn("Error Registering Web Resources", e);
275-
}
274+
initResourcesAndServlets();
275+
276276
}
277277

278-
protected void deactivate(BundleContext context) {
278+
protected void deactivate() {
279279
logger.info("deactivate...");
280280

281281
unregisterAll();
@@ -289,13 +289,16 @@ protected void deactivate(BundleContext context) {
289289

290290
private synchronized void unregisterAll() {
291291

292-
this.contexts.forEach(ServiceRegistration::unregister);
292+
this.wiresBlinkService.stop();
293+
this.eventService.stop();
294+
293295
this.resources.forEach(ServiceRegistration::unregister);
294296
this.servlets.forEach(ServiceRegistration::unregister);
297+
this.contexts.forEach(ServiceRegistration::unregister);
295298

296-
this.wiresBlinkService.stop();
297-
298-
this.eventService.stop();
299+
this.contexts.clear();
300+
this.resources.clear();
301+
this.servlets.clear();
299302

300303
}
301304

@@ -409,8 +412,6 @@ private void updateAuditContext(final HttpSession session) {
409412

410413
}
411414

412-
final Set<String> authenticationPaths = new HashSet<>(Arrays.asList(AUTH_PATH, PASSWORD_AUTH_PATH, CERT_AUTH_PATH));
413-
414415
private SecurityHandler createSessionHandlerChain() {
415416

416417
final Set<String> eventPaths = new HashSet<>(Arrays.asList(DENALI_MODULE_PATH + EVENT_PATH, "/sse"));
@@ -429,7 +430,7 @@ private SecurityHandler createSessionHandlerChain() {
429430
final RoutingSecurityHandler routingHandler = new RoutingSecurityHandler(
430431
defaultHandler.sendErrorOnFailure(401));
431432

432-
// exception on authentication paths, allow access without authenticaton but
433+
// exception on authentication paths, allow access without authentication but
433434
// create a session
434435
routingHandler.addRouteHandler(this.authenticationPaths::contains,
435436
chain(baseHandler, new CreateSessionSecurityHandler()));
@@ -446,92 +447,94 @@ private SecurityHandler createSessionHandlerChain() {
446447
// exception on login session and xsrf path, like default but without locked
447448
// session checking
448449
routingHandler.addRouteHandler(
449-
Arrays.asList(LOGIN_MODULE_PATH + SESSION, LOGIN_MODULE_PATH + "/xsrf")::contains,
450+
Arrays.asList(LOGIN_MODULE_PATH + SESSION, LOGIN_MODULE_PATH + XSRF_PATH)::contains,
450451
chain(baseHandler, sessionAuthHandler, sessionExpirationHandler));
451452

452453
return routingHandler;
453454
}
454455

455-
private synchronized void initHTTPService() throws NamespaceException {
456+
private synchronized void initResourcesAndServlets() {
456457

457458
this.eventService = new GwtEventServiceImpl();
458459
this.wiresBlinkService = new WiresBlinkServlet();
459460

460461
ServletContextHelper resourceContextHelper = new HttpServletContextHelper(new BaseSecurityHandler());
461462
ServletContextHelper sessionContextHelper = new HttpServletContextHelper(createSessionHandlerChain());
462463

463-
registerContextHelper(RESOURCE_CONTEXT_NAME, "/", resourceContextHelper, 5);
464-
registerContextHelper(SESSION_CONTEXT_NAME, "/", sessionContextHelper, 10);
464+
String resourceContextName = RESOURCE_CONTEXT_NAME_PREFIX + System.nanoTime();
465+
String sessionContextName = SESSION_CONTEXT_NAME_PREFIX + System.nanoTime();
466+
467+
registerContextHelper(resourceContextName, "/", resourceContextHelper, 5);
468+
registerContextHelper(sessionContextName, "/", sessionContextHelper, 10);
465469

466-
registerResources(ADMIN_ROOT + "/*", "www", new AdminResources(), RESOURCE_CONTEXT_NAME);
467-
registerResources(AUTH_PATH, "www/auth.html", new AuthorizationResources(), SESSION_CONTEXT_NAME);
468-
registerResources(CONSOLE_PATH, "www/denali.html", new ConsoleResources(), SESSION_CONTEXT_NAME);
470+
registerResources(ADMIN_ROOT + "/*", "www", new AdminResources(), resourceContextName);
471+
registerResources(AUTH_PATH, "www/auth.html", new AuthorizationResources(), sessionContextName);
472+
registerResources(CONSOLE_PATH, "www/denali.html", new ConsoleResources(), sessionContextName);
469473

470474
registerServlet("gwtLoginInfoService", LOGIN_MODULE_PATH + "/loginInfo", new GwtLoginInfoServiceImpl(),
471-
RESOURCE_CONTEXT_NAME);
472-
registerServlet("redirectServlet", "/", new RedirectServlet("/"::equals, this.appRoot), RESOURCE_CONTEXT_NAME);
475+
resourceContextName);
476+
registerServlet("redirectServlet", "/", new RedirectServlet("/"::equals, this.appRoot), resourceContextName);
473477

474478
registerServlet("notFoundAuthResourceServlet", AUTH_RESOURCE_PATH, new SendStatusServlet(404),
475-
RESOURCE_CONTEXT_NAME);
479+
resourceContextName);
476480
registerServlet("notFoundConsoleResourceServlet", CONSOLE_RESOURCE_PATH, new SendStatusServlet(404),
477-
RESOURCE_CONTEXT_NAME);
481+
resourceContextName);
478482

479483
registerServlet("gwtPasswordAuthenticationService", PASSWORD_AUTH_PATH,
480-
new GwtPasswordAuthenticationServiceImpl(this.userManager, CONSOLE_PATH), SESSION_CONTEXT_NAME);
484+
new GwtPasswordAuthenticationServiceImpl(this.userManager, CONSOLE_PATH), sessionContextName);
481485
registerServlet("sslAuthenticationServlet", CERT_AUTH_PATH,
482-
new SslAuthenticationServlet(CONSOLE_PATH, this.userManager), SESSION_CONTEXT_NAME);
486+
new SslAuthenticationServlet(CONSOLE_PATH, this.userManager), sessionContextName);
483487

484488
registerServlet("gwtKeystoreServiceImpl", DENALI_MODULE_PATH + "/keystore", new GwtKeystoreServiceImpl(),
485-
SESSION_CONTEXT_NAME);
489+
sessionContextName);
486490
registerServlet("gwtSslManagerServiceImpl", DENALI_MODULE_PATH + "/ssl", new GwtSslManagerServiceImpl(),
487-
SESSION_CONTEXT_NAME);
491+
sessionContextName);
488492

489493
registerServlet("denaliSessionService", DENALI_MODULE_PATH + SESSION,
490-
new GwtSessionServiceImpl(this.userManager), SESSION_CONTEXT_NAME);
494+
new GwtSessionServiceImpl(this.userManager), sessionContextName);
491495

492496
registerServlet("loginSessionService", LOGIN_MODULE_PATH + SESSION, new GwtSessionServiceImpl(this.userManager),
493-
SESSION_CONTEXT_NAME);
494-
registerServlet("xsrfLoginServlet", LOGIN_MODULE_PATH + "/xsrf", new GwtSecurityTokenServiceImpl(),
495-
SESSION_CONTEXT_NAME);
496-
registerServlet("xsrfDenaliServlet", DENALI_MODULE_PATH + "/xsrf", new GwtSecurityTokenServiceImpl(),
497-
SESSION_CONTEXT_NAME);
497+
sessionContextName);
498+
registerServlet("xsrfLoginServlet", LOGIN_MODULE_PATH + XSRF_PATH, new GwtSecurityTokenServiceImpl(),
499+
sessionContextName);
500+
registerServlet("xsrfDenaliServlet", DENALI_MODULE_PATH + XSRF_PATH, new GwtSecurityTokenServiceImpl(),
501+
sessionContextName);
498502
registerServlet("statusService", DENALI_MODULE_PATH + "/status", new GwtStatusServiceImpl(),
499-
SESSION_CONTEXT_NAME);
503+
sessionContextName);
500504
registerServlet("deviceService", DENALI_MODULE_PATH + "/device", new GwtDeviceServiceImpl(),
501-
SESSION_CONTEXT_NAME);
502-
registerServlet("logService", DENALI_MODULE_PATH + "/logservice", new GwtLogServiceImpl(),
503-
SESSION_CONTEXT_NAME);
505+
sessionContextName);
506+
registerServlet("logService", DENALI_MODULE_PATH + "/logservice", new GwtLogServiceImpl(), sessionContextName);
504507
registerServlet("networkService", DENALI_MODULE_PATH + "/network", new GwtNetworkServiceImpl(),
505-
SESSION_CONTEXT_NAME);
508+
sessionContextName);
506509
registerServlet("componentService", DENALI_MODULE_PATH + "/component", new GwtComponentServiceImpl(),
507-
SESSION_CONTEXT_NAME);
510+
sessionContextName);
508511
registerServlet("packageService", DENALI_MODULE_PATH + "/package",
509-
new GwtPackageServiceImpl(this.sslManagerService::get), SESSION_CONTEXT_NAME);
512+
new GwtPackageServiceImpl(this.sslManagerService::get), sessionContextName);
510513
registerServlet("snapshotServiceImpl", DENALI_MODULE_PATH + "/snapshot", new GwtSnapshotServiceImpl(),
511-
SESSION_CONTEXT_NAME);
514+
sessionContextName);
512515
registerServlet("certificateService", DENALI_MODULE_PATH + "/certificate", new GwtCertificatesServiceImpl(),
513-
SESSION_CONTEXT_NAME);
516+
sessionContextName);
514517
registerServlet("securityService", DENALI_MODULE_PATH + "/security", new GwtSecurityServiceImpl(),
515-
SESSION_CONTEXT_NAME);
518+
sessionContextName);
516519
registerServlet("usersService", DENALI_MODULE_PATH + "/users", new GwtUserServiceImpl(this.userManager),
517-
SESSION_CONTEXT_NAME);
518-
registerServlet("fileServlet", DENALI_MODULE_PATH + "/file/*", new FileServlet(), SESSION_CONTEXT_NAME);
520+
sessionContextName);
521+
registerServlet("fileServlet", DENALI_MODULE_PATH + "/file/*", new FileServlet(), sessionContextName);
519522
registerServlet("deviceSnapshotsServlet", DENALI_MODULE_PATH + "/device_snapshots",
520-
new DeviceSnapshotsServlet(), SESSION_CONTEXT_NAME);
523+
new DeviceSnapshotsServlet(), sessionContextName);
521524
registerServlet("channelServlet", DENALI_MODULE_PATH + "/assetsUpDownload", new ChannelServlet(),
522-
SESSION_CONTEXT_NAME);
523-
registerServlet("logServlet", DENALI_MODULE_PATH + "/log", new LogServlet(), SESSION_CONTEXT_NAME);
524-
registerServlet("skinServlet", DENALI_MODULE_PATH + "/skin/*", new SkinServlet(), RESOURCE_CONTEXT_NAME);
525+
sessionContextName);
526+
registerServlet("logServlet", DENALI_MODULE_PATH + "/log", new LogServlet(), sessionContextName);
527+
registerServlet("skinServlet", DENALI_MODULE_PATH + "/skin/*", new SkinServlet(), resourceContextName);
525528
registerServlet("cloudServices", DENALI_MODULE_PATH + "/cloudservices", new GwtCloudConnectionServiceImpl(),
526-
SESSION_CONTEXT_NAME);
529+
sessionContextName);
527530
registerServlet("wireGraphService", DENALI_MODULE_PATH + "/wires", new GwtWireGraphServiceImpl(),
528-
SESSION_CONTEXT_NAME);
531+
sessionContextName);
529532
registerServlet("wiresSnapshotServlet", DENALI_MODULE_PATH + "/wiresSnapshot", new WiresSnapshotServlet(),
530-
SESSION_CONTEXT_NAME);
533+
sessionContextName);
531534
registerServlet("driverAndAssetService", DENALI_MODULE_PATH + "/assetservices",
532-
new GwtDriverAndAssetServiceImpl(), SESSION_CONTEXT_NAME);
533-
registerServlet("wiresBlinkService", ADMIN_ROOT + "/sse", this.wiresBlinkService, SESSION_CONTEXT_NAME);
534-
registerServlet("eventService", DENALI_MODULE_PATH + EVENT_PATH, this.eventService, SESSION_CONTEXT_NAME);
535+
new GwtDriverAndAssetServiceImpl(), sessionContextName);
536+
registerServlet("wiresBlinkService", ADMIN_ROOT + "/sse", this.wiresBlinkService, sessionContextName);
537+
registerServlet("eventService", DENALI_MODULE_PATH + EVENT_PATH, this.eventService, sessionContextName);
535538

536539
this.eventService.start();
537540
}
@@ -548,37 +551,51 @@ private void registerContextHelper(String contextName, String contextPath, Servl
548551
.registerService(ServletContextHelper.class, contextHelper, new Hashtable<>(props));
549552

550553
this.contexts.add(contextService);
554+
555+
logger.debug("registered context helper with id: {} , name: {} , path {}", //
556+
contextService.getReference().getProperty(Constants.SERVICE_ID), contextName, contextPath);
551557
}
552558

553559
private void registerResources(String pattern, String prefix, ResourcesService resourcesService,
554560
String contextHelperName) {
555561
Map<String, Object> props = new HashMap<>();
556562

563+
String contextHelperSelector = "(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "="
564+
+ contextHelperName + ")";
565+
557566
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN, pattern);
558567
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX, prefix);
559-
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT,
560-
"(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=" + contextHelperName + ")");
568+
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, contextHelperSelector);
561569

562570
ServiceRegistration<ResourcesService> resourcesS = this.bundleContext.registerService(ResourcesService.class,
563571
resourcesService, new Hashtable<>(props));
564572

565573
this.resources.add(resourcesS);
574+
575+
logger.debug("registered resource with id: {} , pattern: {} , prefix {} , contextHelper {}", //
576+
resourcesS.getReference().getProperty(Constants.SERVICE_ID), pattern, prefix, contextHelperSelector);
566577
}
567578

568579
private void registerServlet(String servletName, String servletPattern, HttpServlet servlet,
569580
String contextHelperName) {
570581

571582
Map<String, String> props = new HashMap<>();
572583

584+
String contextHelperSelector = "(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "="
585+
+ contextHelperName + ")";
586+
573587
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, servletName);
574588
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, servletPattern);
575-
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT,
576-
"(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=" + contextHelperName + ")");
589+
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, contextHelperSelector);
577590

578591
ServiceRegistration<Servlet> servletService = this.bundleContext.registerService(Servlet.class, servlet,
579592
new Hashtable<>(props));
580593

581594
this.servlets.add(servletService);
595+
596+
logger.debug("registered servlet with id: {} , name: {} , pattern {} , contextHelper {}", //
597+
servletService.getReference().getProperty(Constants.SERVICE_ID), servletName, servletPattern,
598+
contextHelperSelector);
582599
}
583600

584601
public interface ResourcesService {
@@ -609,4 +626,5 @@ public UserManager getUserManager() {
609626
public ComponentConfiguration getConfiguration() throws KuraException {
610627
return consoleOptions.getConfiguration();
611628
}
629+
612630
}

kura/org.eclipse.kura.web2/src/main/java/org/eclipse/kura/web/server/OsgiRemoteServiceServlet.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@
2222
import java.util.Map;
2323
import java.util.Optional;
2424

25-
import jakarta.servlet.ServletException;
26-
import jakarta.servlet.http.HttpServletRequest;
27-
import jakarta.servlet.http.HttpServletResponse;
28-
2925
import org.eclipse.kura.audit.AuditContext;
3026
import org.eclipse.kura.audit.AuditContext.Scope;
3127
import org.eclipse.kura.web.Console;
@@ -37,9 +33,13 @@
3733
import com.google.gwt.user.server.rpc.SerializationPolicy;
3834
import com.google.gwt.user.server.rpc.SerializationPolicyLoader;
3935

36+
import jakarta.servlet.ServletException;
37+
import jakarta.servlet.http.HttpServletRequest;
38+
import jakarta.servlet.http.HttpServletResponse;
39+
4040
public class OsgiRemoteServiceServlet extends KuraRemoteServiceServlet {
4141

42-
private final Logger auditLogger = LoggerFactory.getLogger("AuditLogger");
42+
private static final Logger auditLogger = LoggerFactory.getLogger("AuditLogger");
4343

4444
private final Optional<RequiredPermissions> servicePermissionRequirements;
4545
private final Map<Method, RequiredPermissions> methodPermissionRequirements = new HashMap<>();
@@ -100,13 +100,13 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws
100100
* alternative approach.
101101
*
102102
* @param request
103-
* the HTTP request being serviced
103+
* the HTTP request being serviced
104104
* @param moduleBaseURL
105-
* as specified in the incoming payload
105+
* as specified in the incoming payload
106106
* @param strongName
107-
* a strong name that uniquely identifies a serialization
108-
* policy
109-
* file
107+
* a strong name that uniquely identifies a serialization
108+
* policy
109+
* file
110110
* @return a {@link SerializationPolicy} for the given module base URL and
111111
* strong name, or <code>null</code> if there is none
112112
*/

0 commit comments

Comments
 (0)