|
42 | 42 | import org.apache.catalina.realm.JAASRealm; |
43 | 43 | import org.apache.catalina.realm.NullRealm; |
44 | 44 | import org.apache.catalina.realm.RealmBase; |
45 | | -import org.red5.logging.Red5LoggerFactory; |
46 | 45 | import org.red5.net.websocket.WebSocketPlugin; |
47 | 46 | import org.red5.server.ContextLoader; |
48 | 47 | import org.red5.server.LoaderBase; |
49 | 48 | import org.red5.server.Server; |
50 | 49 | import org.red5.server.api.IApplicationContext; |
| 50 | +import org.red5.server.api.Red5; |
51 | 51 | import org.red5.server.jmx.mxbeans.ContextLoaderMXBean; |
52 | 52 | import org.red5.server.jmx.mxbeans.LoaderMXBean; |
53 | 53 | import org.red5.server.plugin.PluginRegistry; |
54 | 54 | import org.red5.server.security.IRed5Realm; |
55 | 55 | import org.red5.server.util.FileUtil; |
56 | 56 | import org.slf4j.Logger; |
| 57 | +import org.slf4j.LoggerFactory; |
57 | 58 | import org.springframework.beans.factory.DisposableBean; |
58 | 59 | import org.springframework.beans.factory.InitializingBean; |
59 | 60 | import org.springframework.context.ApplicationContext; |
@@ -115,7 +116,7 @@ public boolean accept(File dir, String name) { |
115 | 116 | private static final String CONTEXT_CLASS_PARAM = "contextClass"; |
116 | 117 |
|
117 | 118 | // Initialize Logging |
118 | | - private static Logger log = Red5LoggerFactory.getLogger(TomcatLoader.class); |
| 119 | + private static Logger log = LoggerFactory.getLogger(TomcatLoader.class); |
119 | 120 |
|
120 | 121 | public static final String defaultSpringConfigLocation = "/WEB-INF/red5-*.xml"; |
121 | 122 |
|
@@ -170,23 +171,43 @@ public boolean accept(File dir, String name) { |
170 | 171 | */ |
171 | 172 | protected boolean websocketEnabled = true; |
172 | 173 |
|
| 174 | + /** |
| 175 | + * Flag to indicate if we should await plugin loading |
| 176 | + */ |
| 177 | + protected boolean awaitPlugins = true; |
| 178 | + |
| 179 | + private static ExecutorService executor; |
| 180 | + |
173 | 181 | @Override |
174 | 182 | public void afterPropertiesSet() throws Exception { |
175 | | - // if websockets are enabled, ensure the websocket plugin is loaded |
176 | | - if (websocketEnabled && PluginRegistry.getPlugin(WebSocketPlugin.NAME) == null) { |
177 | | - // get common context |
178 | | - ApplicationContext common = (ApplicationContext) applicationContext.getBean("red5.common"); |
179 | | - Server server = (Server) common.getBean("red5.server"); |
180 | | - // instance the plugin |
181 | | - WebSocketPlugin plugin = new WebSocketPlugin(); |
182 | | - plugin.setApplicationContext(applicationContext); |
183 | | - plugin.setServer(server); |
184 | | - // register it |
185 | | - PluginRegistry.register(plugin); |
186 | | - // start it |
187 | | - plugin.doStart(); |
| 183 | + // if we are not awaiting plugins, start immediately |
| 184 | + if (awaitPlugins) { |
| 185 | + log.info("Awaiting plugin loading"); |
| 186 | + executor = Executors.newSingleThreadExecutor(); |
| 187 | + executor.submit(() -> { |
| 188 | + final String oldName = Thread.currentThread().getName(); |
| 189 | + Thread.currentThread().setName("TomcatLoader-delayed-start"); |
| 190 | + try { |
| 191 | + while (!Red5.isPluginsReady()) { |
| 192 | + log.debug("Waiting for plugins to load"); |
| 193 | + Thread.sleep(500L); |
| 194 | + } |
| 195 | + start(); |
| 196 | + } catch (ServletException e) { |
| 197 | + log.error("Error starting Tomcat", e); |
| 198 | + } catch (InterruptedException e) { |
| 199 | + log.error("Error waiting for plugins", e); |
| 200 | + } finally { |
| 201 | + Thread.currentThread().setName(oldName); |
| 202 | + } |
| 203 | + }); |
| 204 | + } else { |
| 205 | + try { |
| 206 | + start(); |
| 207 | + } catch (ServletException e) { |
| 208 | + log.error("Error starting Tomcat", e); |
| 209 | + } |
188 | 210 | } |
189 | | - start(); |
190 | 211 | } |
191 | 212 |
|
192 | 213 | /** |
@@ -273,7 +294,11 @@ public void removeContext(String path) { |
273 | 294 | @SuppressWarnings("null") |
274 | 295 | public void start() throws ServletException { |
275 | 296 | log.info("Loading Tomcat"); |
276 | | - //get a reference to the current threads classloader |
| 297 | + // if websockets are enabled, ensure the websocket plugin is loaded |
| 298 | + if (websocketEnabled) { |
| 299 | + checkWebsocketPlugin(); |
| 300 | + } |
| 301 | + // get a reference to the current threads classloader |
277 | 302 | final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); |
278 | 303 | // root location for servlet container |
279 | 304 | String serverRoot = System.getProperty("red5.root"); |
@@ -530,6 +555,27 @@ public void run() { |
530 | 555 | log.debug("Tomcat load completed"); |
531 | 556 | } |
532 | 557 |
|
| 558 | + private void checkWebsocketPlugin() { |
| 559 | + // if websockets are enabled, ensure the websocket plugin is loaded |
| 560 | + if (PluginRegistry.getPlugin(WebSocketPlugin.NAME) == null) { |
| 561 | + // get common context |
| 562 | + ApplicationContext common = (ApplicationContext) applicationContext.getBean("red5.common"); |
| 563 | + Server server = (Server) common.getBean("red5.server"); |
| 564 | + // instance the plugin |
| 565 | + WebSocketPlugin plugin = new WebSocketPlugin(); |
| 566 | + plugin.setApplicationContext(applicationContext); |
| 567 | + plugin.setServer(server); |
| 568 | + // register it |
| 569 | + PluginRegistry.register(plugin); |
| 570 | + // start it |
| 571 | + try { |
| 572 | + plugin.doStart(); |
| 573 | + } catch (Exception e) { |
| 574 | + log.warn("WebSocket plugin start, failed", e); |
| 575 | + } |
| 576 | + } |
| 577 | + } |
| 578 | + |
533 | 579 | /** |
534 | 580 | * Starts a web application and its red5 (spring) component. This is basically a stripped down version of start(). |
535 | 581 | * |
@@ -803,6 +849,15 @@ public void setWebsocketEnabled(boolean websocketEnabled) { |
803 | 849 | this.websocketEnabled = websocketEnabled; |
804 | 850 | } |
805 | 851 |
|
| 852 | + /** |
| 853 | + * Returns await plugin loading state. |
| 854 | + * |
| 855 | + * @return true if awaiting plugin loading and false otherwise |
| 856 | + */ |
| 857 | + public void setAwaitPlugins(boolean awaitPlugins) { |
| 858 | + this.awaitPlugins = awaitPlugins; |
| 859 | + } |
| 860 | + |
806 | 861 | /** |
807 | 862 | * Returns a semi-unique id for this host based on its host values |
808 | 863 | * |
@@ -846,6 +901,9 @@ protected void unregisterJMX() { |
846 | 901 | @Override |
847 | 902 | public void destroy() throws Exception { |
848 | 903 | log.info("Shutting down Tomcat context"); |
| 904 | + if (executor != null) { |
| 905 | + executor.shutdown(); |
| 906 | + } |
849 | 907 | // run through the applications and ensure that spring is told to commence shutdown / disposal |
850 | 908 | AbstractApplicationContext absCtx = (AbstractApplicationContext) LoaderBase.getApplicationContext(); |
851 | 909 | if (absCtx != null) { |
|
0 commit comments