Skip to content

Commit 575fe1b

Browse files
committed
Refactored Tomcat and WarDeployer, removing control from Spring and placing in the loader.
1 parent 6b3ea15 commit 575fe1b

3 files changed

Lines changed: 57 additions & 100 deletions

File tree

server/src/main/java/org/red5/server/tomcat/TomcatLoader.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@
2222
import javax.management.JMX;
2323
import javax.management.MBeanServer;
2424
import javax.management.ObjectName;
25-
import jakarta.security.auth.message.config.AuthConfigFactory;
26-
import jakarta.servlet.ServletContext;
27-
import jakarta.servlet.ServletException;
2825

2926
import org.apache.catalina.Container;
3027
import org.apache.catalina.Context;
@@ -64,6 +61,10 @@
6461
import org.springframework.web.context.WebApplicationContext;
6562
import org.springframework.web.context.support.XmlWebApplicationContext;
6663

64+
import jakarta.security.auth.message.config.AuthConfigFactory;
65+
import jakarta.servlet.ServletContext;
66+
import jakarta.servlet.ServletException;
67+
6768
/**
6869
* Red5 loader for Tomcat.
6970
*
@@ -178,6 +179,11 @@ public boolean accept(File dir, String name) {
178179

179180
private static ExecutorService executor;
180181

182+
/**
183+
* War deployer
184+
*/
185+
private WarDeployer deployer;
186+
181187
@Override
182188
public void afterPropertiesSet() throws Exception {
183189
// if we are not awaiting plugins, start immediately
@@ -189,8 +195,8 @@ public void afterPropertiesSet() throws Exception {
189195
Thread.currentThread().setName("TomcatLoader-delayed-start");
190196
try {
191197
while (!Red5.isPluginsReady()) {
192-
log.debug("Waiting for plugins to load");
193-
Thread.sleep(500L);
198+
log.trace("Waiting for plugins to load");
199+
Thread.sleep(2000L);
194200
}
195201
start();
196202
} catch (ServletException e) {
@@ -291,7 +297,6 @@ public void removeContext(String path) {
291297
/**
292298
* Initialization.
293299
*/
294-
@SuppressWarnings("null")
295300
public void start() throws ServletException {
296301
log.info("Loading Tomcat");
297302
// if websockets are enabled, ensure the websocket plugin is loaded
@@ -332,6 +337,8 @@ public void start() throws ServletException {
332337
log.info("Application root: {}", webappFolder);
333338
// Root applications directory
334339
File appDirBase = new File(webappFolder);
340+
// create/start the war deployer, but don't start any expanded apps, yet
341+
deployer = new WarDeployer(appDirBase, true);
335342
// Subdirs of root apps dir
336343
File[] dirs = appDirBase.listFiles(new DirectoryFilter());
337344
// Search for additional context files
@@ -531,7 +538,7 @@ public void run() {
531538
applicationContext.getBean("rtmpt.server");
532539
log.debug("Finished initializing RTMPT");
533540
} else {
534-
log.info("Dedicated RTMPT server configuration was not specified");
541+
log.debug("Dedicated RTMPT server configuration was not specified");
535542
}
536543
if (applicationContext.containsBean("rtmps.server")) {
537544
log.debug("Initializing RTMPS");
@@ -901,6 +908,10 @@ protected void unregisterJMX() {
901908
@Override
902909
public void destroy() throws Exception {
903910
log.info("Shutting down Tomcat context");
911+
if (deployer != null) {
912+
deployer.stop();
913+
deployer = null;
914+
}
904915
if (executor != null) {
905916
executor.shutdown();
906917
}

server/src/main/java/org/red5/server/tomcat/WarDeployer.java

Lines changed: 39 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -19,39 +19,35 @@
1919
import javax.management.JMX;
2020
import javax.management.MBeanServer;
2121
import javax.management.ObjectName;
22-
import jakarta.servlet.ServletException;
2322

24-
import org.red5.server.LoaderBase;
2523
import org.red5.server.jmx.mxbeans.LoaderMXBean;
2624
import org.red5.server.util.FileUtil;
2725
import org.slf4j.Logger;
2826
import org.slf4j.LoggerFactory;
2927
import org.springframework.beans.BeansException;
30-
import org.springframework.beans.factory.DisposableBean;
31-
import org.springframework.beans.factory.InitializingBean;
3228
import org.springframework.context.ApplicationContext;
3329
import org.springframework.context.ApplicationContextAware;
3430

31+
import jakarta.servlet.ServletException;
32+
3533
/**
3634
* This service provides the means to auto-deploy a war.
3735
*
36+
* Note: This class has deprecated use of Spring and has been refactored to be instantiated and controlled via the
37+
* TomcatLoader, it is no longer meant to be used in the jee-container.xml as a bean.
38+
*
3839
* @author Paul Gregoire (mondain@gmail.com)
3940
*/
40-
public final class WarDeployer implements ApplicationContextAware, InitializingBean, DisposableBean {
41+
public final class WarDeployer implements ApplicationContextAware {
4142

4243
private Logger log = LoggerFactory.getLogger(WarDeployer.class);
4344

4445
//that wars are currently being installed
4546
private static AtomicBoolean deploying = new AtomicBoolean(false);
4647

47-
/**
48-
* Spring Application context
49-
*/
50-
private ApplicationContext applicationContext;
51-
5248
private ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
5349

54-
private ScheduledFuture<DeployJob> future;
50+
private ScheduledFuture<?> future;
5551

5652
/**
5753
* How often to check for new war files
@@ -61,48 +57,36 @@ public final class WarDeployer implements ApplicationContextAware, InitializingB
6157
/**
6258
* Deployment directory
6359
*/
64-
private String webappFolder;
65-
66-
/**
67-
* Expand WAR files in the webapps directory prior to start up
68-
*/
69-
private boolean expandWars;
60+
private final File webappsDirectory;
7061

7162
{
7263
log.info("War deployer service created");
7364
}
7465

75-
@SuppressWarnings("unchecked")
76-
@Override
77-
public void afterPropertiesSet() throws Exception {
78-
log.info("Starting WarDeployer");
79-
// create the job and schedule it
80-
future = (ScheduledFuture<DeployJob>) scheduler.scheduleAtFixedRate(new DeployJob(), 60000L, checkInterval, TimeUnit.MILLISECONDS);
81-
// check the deploy from directory
82-
log.debug("Webapps directory: {}", webappFolder);
83-
File dir = new File(webappFolder);
84-
if (!dir.exists()) {
85-
log.warn("Source directory not found");
86-
} else {
87-
if (!dir.isDirectory()) {
88-
throw new Exception("Webapps directory is not a directory");
89-
}
90-
}
91-
dir = null;
66+
@Deprecated(since = "2.0.9", forRemoval = true)
67+
public WarDeployer() {
68+
log.warn("Use via constructor or as a Spring bean is deprecated");
69+
webappsDirectory = new File("webapps");
70+
}
71+
72+
public WarDeployer(File webappsDirectory) {
73+
this(webappsDirectory, false);
74+
}
75+
76+
public WarDeployer(File webappsDirectory, boolean expandWars) {
77+
log.info("Starting WarDeployer - webapps directory: {}", webappsDirectory.getAbsolutePath());
78+
// set the webapp folder
79+
this.webappsDirectory = webappsDirectory;
9280
// expand wars if so requested
9381
if (expandWars) {
94-
log.debug("Deploying wars");
82+
log.debug("Deploying wars, not starting applications");
9583
deploy(false);
9684
}
97-
try {
98-
// check for an embedded jee server
99-
LoaderBase jeeServer = applicationContext.getBean(LoaderBase.class);
100-
// lookup the jee container
101-
if (jeeServer != null) {
102-
log.info("JEE server was found: {}", jeeServer.toString());
103-
}
104-
} catch (Exception e) {
105-
}
85+
// create the job and schedule it
86+
future = (ScheduledFuture<?>) scheduler.scheduleAtFixedRate(() -> {
87+
log.debug("Starting scheduled deployment of wars");
88+
deploy(true);
89+
}, 60000L, checkInterval, TimeUnit.MILLISECONDS);
10690
}
10791

10892
private void deploy(boolean startApplication) {
@@ -112,10 +96,8 @@ private void deploy(boolean startApplication) {
11296
String application = null;
11397
// file name
11498
String applicationWarName = null;
115-
// look for web application archives
116-
File dir = new File(webappFolder);
11799
// get a list of wars
118-
File[] files = dir.listFiles(new DirectoryFilter());
100+
File[] files = webappsDirectory.listFiles(new DirectoryFilter());
119101
for (File f : files) {
120102
// get the war name
121103
applicationWarName = f.getName();
@@ -130,10 +112,10 @@ private void deploy(boolean startApplication) {
130112
log.debug("Application name: {}", application);
131113
// setup context
132114
String contextPath = '/' + application;
133-
String contextDir = webappFolder + contextPath;
115+
String contextDir = webappsDirectory.getAbsolutePath() + contextPath;
134116
log.debug("Web context: {} context directory: {}", contextPath, contextDir);
135117
// verify this is a unique app
136-
File appDir = new File(dir, application);
118+
File appDir = new File(webappsDirectory, application);
137119
if (appDir.exists()) {
138120
if (appDir.isDirectory()) {
139121
log.debug("Application directory exists");
@@ -144,7 +126,7 @@ private void deploy(boolean startApplication) {
144126
} else {
145127
log.debug("Unwaring and starting...");
146128
// un-archive it to app dir
147-
FileUtil.unzip(webappFolder + '/' + applicationWarName, contextDir);
129+
FileUtil.unzip(webappsDirectory.getAbsolutePath() + '/' + applicationWarName, contextDir);
148130
// load and start the context
149131
if (startApplication) {
150132
// get the webapp loader from jmx
@@ -158,7 +140,7 @@ private void deploy(boolean startApplication) {
158140
}
159141
}
160142
// remove the war file
161-
File warFile = new File(dir, applicationWarName);
143+
File warFile = new File(webappsDirectory, applicationWarName);
162144
if (warFile.delete()) {
163145
log.debug("{} was deleted", warFile.getName());
164146
} else {
@@ -169,26 +151,18 @@ private void deploy(boolean startApplication) {
169151
}
170152
appDir = null;
171153
}
172-
dir = null;
173154
// reset sentinel
174155
deploying.set(false);
175156
}
176157
}
177158

178-
@Override
179-
public void destroy() throws Exception {
159+
public void stop() throws Exception {
180160
if (future != null) {
181161
future.cancel(true);
182162
}
183163
scheduler.shutdownNow();
184164
}
185165

186-
@SuppressWarnings("null")
187-
@Override
188-
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
189-
this.applicationContext = applicationContext;
190-
}
191-
192166
public void setCheckInterval(int checkInterval) {
193167
this.checkInterval = checkInterval;
194168
}
@@ -197,24 +171,6 @@ public int getCheckInterval() {
197171
return checkInterval;
198172
}
199173

200-
public String getWebappFolder() {
201-
return webappFolder;
202-
}
203-
204-
public void setWebappFolder(String webappFolder) {
205-
this.webappFolder = webappFolder;
206-
}
207-
208-
/**
209-
* Whether or not to expand war files prior to start up.
210-
*
211-
* @param expandWars
212-
* to expand or not
213-
*/
214-
public void setExpandWars(boolean expandWars) {
215-
this.expandWars = expandWars;
216-
}
217-
218174
/**
219175
* Returns the LoaderMBean.
220176
*
@@ -263,13 +219,11 @@ public boolean accept(File dir, String name) {
263219
}
264220
}
265221

266-
private class DeployJob implements Runnable {
267-
268-
public void run() {
269-
log.debug("Starting scheduled deployment of wars");
270-
deploy(true);
271-
}
272-
222+
@Deprecated(since = "2.0.9", forRemoval = true)
223+
@SuppressWarnings("null")
224+
@Override
225+
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
226+
log.warn("This method is deprecated and should not be used; instances are created and controlled internally via TomcatLoader");
273227
}
274228

275229
}

server/src/main/server/conf/jee-container.xml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,6 @@
55
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
66
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd">
77

8-
<!-- War deployer -->
9-
<bean id="warDeployer" class="org.red5.server.tomcat.WarDeployer">
10-
<property name="checkInterval" value="${war.deploy.server.check.interval}"/>
11-
<property name="webappFolder" value="${red5.root}/webapps"/>
12-
<!-- Expand war files prior to startup of the remaining services -->
13-
<property name="expandWars" value="true" />
14-
</bean>
15-
168
<!--
179
The tomcat connectors may be blocking or non-blocking. Select between either option via the protocol property.
1810
Blocking I/O:

0 commit comments

Comments
 (0)