2 * Copyright (c) 2023 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.restconf.nb.rfc8040.streams;
10 import static java.util.Objects.requireNonNull;
14 import javax.servlet.http.HttpServlet;
15 import javax.ws.rs.core.Application;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.opendaylight.aaa.web.servlet.ServletSupport;
18 import org.opendaylight.restconf.api.query.PrettyPrintParam;
19 import org.opendaylight.restconf.nb.rfc8040.ErrorTagMapping;
20 import org.opendaylight.restconf.server.spi.RestconfStream;
21 import org.osgi.service.component.annotations.Activate;
22 import org.osgi.service.component.annotations.Component;
23 import org.osgi.service.component.annotations.Deactivate;
24 import org.osgi.service.component.annotations.Reference;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
29 * Auxiliary interface for instantiating JAX-RS streams.
31 * @deprecated This componet exists only to support SSE/Websocket delivery. It will be removed when support for
32 * WebSockets is removed.
34 @Component(factory = DefaultRestconfStreamServletFactory.FACTORY_NAME, service = RestconfStreamServletFactory.class)
35 @Deprecated(since = "7.0.0", forRemoval = true)
36 public final class DefaultRestconfStreamServletFactory implements RestconfStreamServletFactory, AutoCloseable {
37 private static final Logger LOG = LoggerFactory.getLogger(DefaultRestconfStreamServletFactory.class);
39 public static final String FACTORY_NAME =
40 "org.opendaylight.restconf.nb.rfc8040.streams.RestconfStreamServletFactory";
42 private static final String PROP_STREAM_REGISTRY = ".streamRegistry";
43 private static final String PROP_NAME_PREFIX = ".namePrefix";
44 private static final String PROP_CORE_POOL_SIZE = ".corePoolSize";
45 private static final String PROP_USE_WEBSOCKETS = ".useWebsockets";
46 private static final String PROP_STREAMS_CONFIGURATION = ".streamsConfiguration";
47 private static final String PROP_RESTCONF = ".restconf";
48 private static final String PROP_PRETTY_PRINT = ".prettyPrint";
49 private static final String PROP_ERROR_TAG_MAPPING = ".errorTagMapping";
51 private final @NonNull String restconf;
52 private final @NonNull ErrorTagMapping errorTagMapping;
53 private final @NonNull PrettyPrintParam prettyPrint;
54 private final RestconfStream.Registry streamRegistry;
55 private final ServletSupport servletSupport;
57 private final DefaultPingExecutor pingExecutor;
58 private final StreamsConfiguration streamsConfiguration;
59 private final boolean useWebsockets;
61 public DefaultRestconfStreamServletFactory(final ServletSupport servletSupport, final String restconf,
62 final RestconfStream.Registry streamRegistry, final StreamsConfiguration streamsConfiguration,
63 final ErrorTagMapping errorTagMapping, final PrettyPrintParam prettyPrint, final String namePrefix,
64 final int corePoolSize, final boolean useWebsockets) {
65 this.servletSupport = requireNonNull(servletSupport);
66 this.restconf = requireNonNull(restconf);
67 if (restconf.endsWith("/")) {
68 throw new IllegalArgumentException("{+restconf} value ends with /");
70 this.streamRegistry = requireNonNull(streamRegistry);
71 this.streamsConfiguration = requireNonNull(streamsConfiguration);
72 this.errorTagMapping = requireNonNull(errorTagMapping);
73 this.prettyPrint = requireNonNull(prettyPrint);
74 pingExecutor = new DefaultPingExecutor(namePrefix, corePoolSize);
75 this.useWebsockets = useWebsockets;
78 RESTCONF event streams use WebSockets instead of Server-Sent Events. This option is will be removed in
79 the next major release.""");
84 public DefaultRestconfStreamServletFactory(@Reference final ServletSupport servletSupport,
85 final Map<String, ?> props) {
86 this(servletSupport, (String) props.get(PROP_RESTCONF),
87 (RestconfStream.Registry) props.get(PROP_STREAM_REGISTRY),
88 (StreamsConfiguration) props.get(PROP_STREAMS_CONFIGURATION),
89 (ErrorTagMapping) props.get(PROP_ERROR_TAG_MAPPING),
90 (PrettyPrintParam) props.get(PROP_PRETTY_PRINT),
91 (String) props.get(PROP_NAME_PREFIX), (int) requireNonNull(props.get(PROP_CORE_POOL_SIZE)),
92 (boolean) requireNonNull(props.get(PROP_USE_WEBSOCKETS)));
96 public String restconf() {
101 public HttpServlet newStreamServlet() {
102 return useWebsockets ? new WebSocketInitializer(restconf, streamRegistry, pingExecutor, streamsConfiguration)
103 : servletSupport.createHttpServletBuilder(
106 public Set<Object> getSingletons() {
107 return Set.of(new SSEStreamService(streamRegistry, pingExecutor, streamsConfiguration));
113 public PrettyPrintParam prettyPrint() {
118 public ErrorTagMapping errorTagMapping() {
119 return errorTagMapping;
124 public void close() {
125 pingExecutor.close();
128 public static Map<String, ?> props(final String restconf, final RestconfStream.Registry streamRegistry,
129 final ErrorTagMapping errorTagMapping, final PrettyPrintParam prettyPrint, final boolean useSSE,
130 final StreamsConfiguration streamsConfiguration, final String namePrefix, final int corePoolSize) {
132 PROP_RESTCONF, restconf,
133 PROP_STREAM_REGISTRY, streamRegistry,
134 PROP_ERROR_TAG_MAPPING, errorTagMapping,
135 PROP_PRETTY_PRINT, prettyPrint,
136 PROP_USE_WEBSOCKETS, !useSSE,
137 PROP_STREAMS_CONFIGURATION, streamsConfiguration,
138 PROP_NAME_PREFIX, namePrefix,
139 PROP_CORE_POOL_SIZE, corePoolSize);