Make SSEStreamService class public
[netconf.git] / restconf / restconf-nb / src / main / java / org / opendaylight / restconf / nb / rfc8040 / streams / DefaultRestconfStreamServletFactory.java
1 /*
2  * Copyright (c) 2023 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.restconf.nb.rfc8040.streams;
9
10 import static java.util.Objects.requireNonNull;
11
12 import java.util.Map;
13 import java.util.Set;
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;
27
28 /**
29  * Auxiliary interface for instantiating JAX-RS streams.
30  *
31  * @deprecated This componet exists only to support SSE/Websocket delivery. It will be removed when support for
32  *             WebSockets is removed.
33  */
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);
38
39     public static final String FACTORY_NAME =
40         "org.opendaylight.restconf.nb.rfc8040.streams.RestconfStreamServletFactory";
41
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";
50
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;
56
57     private final DefaultPingExecutor pingExecutor;
58     private final StreamsConfiguration streamsConfiguration;
59     private final boolean useWebsockets;
60
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 /");
69         }
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;
76         if (useWebsockets) {
77             LOG.warn("""
78                 RESTCONF event streams use WebSockets instead of Server-Sent Events. This option is will be removed in
79                 the next major release.""");
80         }
81     }
82
83     @Activate
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)));
93     }
94
95     @Override
96     public String restconf() {
97         return restconf;
98     }
99
100     @Override
101     public HttpServlet newStreamServlet() {
102         return useWebsockets ? new WebSocketInitializer(restconf, streamRegistry, pingExecutor, streamsConfiguration)
103             : servletSupport.createHttpServletBuilder(
104                 new Application() {
105                     @Override
106                     public Set<Object> getSingletons() {
107                         return Set.of(new SSEStreamService(streamRegistry, pingExecutor, streamsConfiguration));
108                     }
109                 }).build();
110     }
111
112     @Override
113     public PrettyPrintParam prettyPrint() {
114         return prettyPrint;
115     }
116
117     @Override
118     public ErrorTagMapping errorTagMapping() {
119         return errorTagMapping;
120     }
121
122     @Override
123     @Deactivate
124     public void close() {
125         pingExecutor.close();
126     }
127
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) {
131         return Map.of(
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);
140     }
141 }