Add configuration to allow deferring the initial Deployment until after Server is started (#10667)
* Delayed Deployment configuration until after Server is started. Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
This commit is contained in:
parent
536a38aa8e
commit
909e99ec37
|
@ -59,5 +59,9 @@
|
|||
<artifactId>jetty-test-helper</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.awaitility</groupId>
|
||||
<artifactId>awaitility</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
</Default>
|
||||
</Property>
|
||||
</Set>
|
||||
<Set name="deferInitialScan"><Property name="jetty.deploy.deferInitialScan" default="false"/></Set>
|
||||
<Set name="scanInterval"><Property name="jetty.deploy.scanInterval" default="1"/></Set>
|
||||
<Set name="extractWars"><Property name="jetty.deploy.extractWars" default="true"/></Set>
|
||||
<Set name="configurationManager">
|
||||
|
|
|
@ -20,8 +20,15 @@ etc/jetty-deploy.xml
|
|||
# Defaults Descriptor for all deployed webapps
|
||||
# jetty.deploy.defaultsDescriptorPath=${jetty.base}/etc/webdefault.xml
|
||||
|
||||
# Defer Initial Scan
|
||||
# true to have the initial scan deferred until the Server component is started.
|
||||
# Note: deploy failures do not fail server startup in a deferred initial scan mode.
|
||||
# false (default) to have initial scan occur as normal.
|
||||
# jetty.deploy.deferInitialScan=false
|
||||
|
||||
# Monitored directory scan period (seconds)
|
||||
# jetty.deploy.scanInterval=1
|
||||
|
||||
# Whether to extract *.war files
|
||||
# jetty.deploy.extractWars=true
|
||||
|
||||
|
|
|
@ -27,11 +27,13 @@ import java.util.stream.Collectors;
|
|||
import org.eclipse.jetty.deploy.App;
|
||||
import org.eclipse.jetty.deploy.AppProvider;
|
||||
import org.eclipse.jetty.deploy.DeploymentManager;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.util.Scanner;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
import org.eclipse.jetty.util.annotation.ManagedOperation;
|
||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -49,6 +51,7 @@ public abstract class ScanningAppProvider extends ContainerLifeCycle implements
|
|||
private int _scanInterval = 10;
|
||||
private Scanner _scanner;
|
||||
private boolean _useRealPaths;
|
||||
private boolean _deferInitialScan = false;
|
||||
|
||||
private final Scanner.DiscreteListener _scannerListener = new Scanner.DiscreteListener()
|
||||
{
|
||||
|
@ -152,9 +155,30 @@ public abstract class ScanningAppProvider extends ContainerLifeCycle implements
|
|||
_scanner.setReportDirs(true);
|
||||
_scanner.setScanDepth(1); //consider direct dir children of monitored dir
|
||||
_scanner.addListener(_scannerListener);
|
||||
|
||||
_scanner.setReportExistingFilesOnStartup(true);
|
||||
_scanner.setAutoStartScanning(!_deferInitialScan);
|
||||
addBean(_scanner);
|
||||
|
||||
if (isDeferInitialScan())
|
||||
{
|
||||
// Setup listener to wait for Server in STARTED state, which
|
||||
// triggers the first scan of the monitored directories
|
||||
getDeploymentManager().getServer().addEventListener(
|
||||
new LifeCycle.Listener()
|
||||
{
|
||||
@Override
|
||||
public void lifeCycleStarted(LifeCycle event)
|
||||
{
|
||||
if (event instanceof Server)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Triggering Deferred Scan of {}", _monitored);
|
||||
_scanner.startScanning();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
|
@ -296,6 +320,34 @@ public abstract class ScanningAppProvider extends ContainerLifeCycle implements
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if initial scan should be deferred.
|
||||
*
|
||||
* @return true if initial scan is deferred, false to have initial scan occur on startup of ScanningAppProvider.
|
||||
*/
|
||||
public boolean isDeferInitialScan()
|
||||
{
|
||||
return _deferInitialScan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag to control initial scan behavior.
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@code true} - to have initial scan deferred until the {@link Server} component
|
||||
* has reached it's STARTED state.<br>
|
||||
* Note: any failures in a deploy will not fail the Server startup in this mode.</li>
|
||||
* <li>{@code false} - (default value) to have initial scan occur as normal on
|
||||
* ScanningAppProvider startup.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param defer true to defer initial scan, false to have initial scan occur on startup of ScanningAppProvider.
|
||||
*/
|
||||
public void setDeferInitialScan(boolean defer)
|
||||
{
|
||||
_deferInitialScan = defer;
|
||||
}
|
||||
|
||||
public void setScanInterval(int scanInterval)
|
||||
{
|
||||
_scanInterval = scanInterval;
|
||||
|
|
|
@ -17,30 +17,41 @@ import java.io.File;
|
|||
import java.nio.file.FileSystemException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.deploy.AppProvider;
|
||||
import org.eclipse.jetty.deploy.DeploymentManager;
|
||||
import org.eclipse.jetty.deploy.test.XmlConfiguredJetty;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.server.handler.HandlerCollection;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
|
||||
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.Scanner;
|
||||
import org.eclipse.jetty.util.component.Container;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledOnOs;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
import static org.junit.jupiter.api.condition.OS.LINUX;
|
||||
|
@ -52,8 +63,7 @@ public class WebAppProviderTest
|
|||
private static XmlConfiguredJetty jetty;
|
||||
private boolean symlinkSupported = false;
|
||||
|
||||
@BeforeEach
|
||||
public void setupEnvironment() throws Exception
|
||||
private void startEnvironment() throws Exception
|
||||
{
|
||||
Path p = testdir.getEmptyPathDir();
|
||||
jetty = new XmlConfiguredJetty(p);
|
||||
|
@ -97,8 +107,9 @@ public class WebAppProviderTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testStartupContext()
|
||||
public void testStartupContext() throws Exception
|
||||
{
|
||||
startEnvironment();
|
||||
assumeTrue(symlinkSupported);
|
||||
|
||||
// Check Server for Handlers
|
||||
|
@ -115,8 +126,9 @@ public class WebAppProviderTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testStartupSymlinkContext()
|
||||
public void testStartupSymlinkContext() throws Exception
|
||||
{
|
||||
startEnvironment();
|
||||
assumeTrue(symlinkSupported);
|
||||
|
||||
// Check for path
|
||||
|
@ -139,17 +151,11 @@ public class WebAppProviderTest
|
|||
@EnabledOnOs({LINUX})
|
||||
public void testWebappSymlinkDir() throws Exception
|
||||
{
|
||||
jetty.stop(); //reconfigure jetty
|
||||
|
||||
testdir.ensureEmpty();
|
||||
|
||||
jetty = new XmlConfiguredJetty(testdir.getEmptyPathDir());
|
||||
jetty.addConfiguration("jetty.xml");
|
||||
jetty.addConfiguration("jetty-http.xml");
|
||||
jetty.addConfiguration("jetty-deploy-wars.xml");
|
||||
|
||||
assumeTrue(symlinkSupported);
|
||||
|
||||
//delete the existing webapps directory
|
||||
File webapps = jetty.getJettyDir("webapps");
|
||||
assertTrue(IO.delete(webapps));
|
||||
|
@ -159,14 +165,25 @@ public class WebAppProviderTest
|
|||
Files.createDirectory(x.toPath());
|
||||
|
||||
//Put a webapp into it
|
||||
File srcDir = MavenTestingUtils.getTestResourceDir("webapps");
|
||||
Path srcDir = MavenTestingUtils.getTestResourcePathDir("webapps");
|
||||
File fooWar = new File(x, "foo.war");
|
||||
IO.copy(new File(srcDir, "foo-webapp-1.war"), fooWar);
|
||||
IO.copy(srcDir.resolve("foo-webapp-1.war").toFile(), fooWar);
|
||||
assertTrue(Files.exists(fooWar.toPath()));
|
||||
|
||||
//make a link from x to webapps
|
||||
Files.createSymbolicLink(jetty.getJettyDir("webapps").toPath(), x.toPath());
|
||||
assertTrue(Files.exists(jetty.getJettyDir("webapps").toPath()));
|
||||
try
|
||||
{
|
||||
//make a link from x to webapps
|
||||
Files.createSymbolicLink(jetty.getJettyDir("webapps").toPath(), x.toPath());
|
||||
assertTrue(Files.exists(jetty.getJettyDir("webapps").toPath()));
|
||||
symlinkSupported = true;
|
||||
}
|
||||
catch (UnsupportedOperationException | FileSystemException e)
|
||||
{
|
||||
// if unable to create symlink, no point testing that feature
|
||||
// this is the path that Microsoft Windows takes.
|
||||
symlinkSupported = false;
|
||||
}
|
||||
assumeTrue(symlinkSupported);
|
||||
|
||||
jetty.load();
|
||||
jetty.start();
|
||||
|
@ -179,10 +196,6 @@ public class WebAppProviderTest
|
|||
@EnabledOnOs({LINUX})
|
||||
public void testBaseDirSymlink() throws Exception
|
||||
{
|
||||
jetty.stop(); //reconfigure jetty
|
||||
|
||||
testdir.ensureEmpty();
|
||||
|
||||
Path realBase = testdir.getEmptyPathDir();
|
||||
|
||||
//set jetty up on the real base
|
||||
|
@ -202,8 +215,8 @@ public class WebAppProviderTest
|
|||
jetty.stop();
|
||||
|
||||
//Make a symbolic link to the real base
|
||||
File testsDir = MavenTestingUtils.getTargetTestingDir();
|
||||
Path symlinkBase = Files.createSymbolicLink(testsDir.toPath().resolve("basedirsymlink-" + System.currentTimeMillis()), jettyHome);
|
||||
Path testsDir = MavenTestingUtils.getTargetTestingPath();
|
||||
Files.createSymbolicLink(testsDir.resolve("basedirsymlink-" + System.currentTimeMillis()), jettyHome);
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
properties.put("jetty.home", jettyHome.toString());
|
||||
//Start jetty, but this time running from the symlinked base
|
||||
|
@ -215,7 +228,6 @@ public class WebAppProviderTest
|
|||
try
|
||||
{
|
||||
server.start();
|
||||
HandlerCollection handlers = (HandlerCollection)server.getHandler();
|
||||
Handler[] children = server.getChildHandlersByClass(WebAppContext.class);
|
||||
assertEquals(1, children.length);
|
||||
assertEquals("/foo", ((WebAppContext)children[0]).getContextPath());
|
||||
|
@ -225,12 +237,143 @@ public class WebAppProviderTest
|
|||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> setupJettyProperties(Path jettyHome)
|
||||
|
||||
@Test
|
||||
public void testDelayedDeploy() throws Exception
|
||||
{
|
||||
Path realBase = testdir.getEmptyPathDir();
|
||||
|
||||
//set jetty up on the real base
|
||||
jetty = new XmlConfiguredJetty(realBase);
|
||||
jetty.addConfiguration("jetty.xml");
|
||||
jetty.addConfiguration("jetty-http.xml");
|
||||
jetty.addConfiguration("jetty-deploy-wars.xml");
|
||||
|
||||
//Put a webapp into the base
|
||||
jetty.copyWebapp("foo-webapp-1.war", "foo.war");
|
||||
|
||||
Path jettyHome = jetty.getJettyHome().toPath();
|
||||
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
properties.put("jetty.home", jettyHome.toFile().getAbsolutePath());
|
||||
return properties;
|
||||
properties.put("jetty.home", jettyHome.toString());
|
||||
properties.put("jetty.deploy.deferInitialScan", "true");
|
||||
//Start jetty, but this time running from the symlinked base
|
||||
System.setProperty("jetty.home", properties.get("jetty.home"));
|
||||
|
||||
List<Resource> configurations = jetty.getConfigurations();
|
||||
Server server = XmlConfiguredJetty.loadConfigurations(configurations, properties);
|
||||
|
||||
try
|
||||
{
|
||||
BlockingQueue<String> eventQueue = new LinkedBlockingDeque<>();
|
||||
|
||||
LifeCycle.Listener eventCaptureListener = new LifeCycle.Listener()
|
||||
{
|
||||
@Override
|
||||
public void lifeCycleStarted(LifeCycle event)
|
||||
{
|
||||
if (event instanceof Server)
|
||||
{
|
||||
eventQueue.add("Server started");
|
||||
}
|
||||
if (event instanceof ScanningAppProvider)
|
||||
{
|
||||
eventQueue.add("ScanningAppProvider started");
|
||||
}
|
||||
if (event instanceof Scanner)
|
||||
{
|
||||
eventQueue.add("Scanner started");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
server.addEventListener(eventCaptureListener);
|
||||
|
||||
ScanningAppProvider scanningAppProvider = null;
|
||||
DeploymentManager deploymentManager = server.getBean(DeploymentManager.class);
|
||||
for (AppProvider appProvider : deploymentManager.getAppProviders())
|
||||
{
|
||||
if (appProvider instanceof ScanningAppProvider)
|
||||
{
|
||||
scanningAppProvider = (ScanningAppProvider)appProvider;
|
||||
}
|
||||
}
|
||||
assertNotNull(scanningAppProvider, "Should have found ScanningAppProvider");
|
||||
assertTrue(scanningAppProvider.isDeferInitialScan(), "The DeferInitialScan configuration should be true");
|
||||
|
||||
scanningAppProvider.addEventListener(eventCaptureListener);
|
||||
scanningAppProvider.addEventListener(new Container.InheritedListener()
|
||||
{
|
||||
@Override
|
||||
public void beanAdded(Container parent, Object child)
|
||||
{
|
||||
if (child instanceof Scanner)
|
||||
{
|
||||
Scanner scanner = (Scanner)child;
|
||||
scanner.addEventListener(eventCaptureListener);
|
||||
scanner.addListener(new Scanner.ScanCycleListener()
|
||||
{
|
||||
@Override
|
||||
public void scanStarted(int cycle) throws Exception
|
||||
{
|
||||
eventQueue.add("Scan Started [" + cycle + "]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scanEnded(int cycle) throws Exception
|
||||
{
|
||||
eventQueue.add("Scan Ended [" + cycle + "]");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beanRemoved(Container parent, Object child)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
|
||||
server.start();
|
||||
|
||||
// Wait till the webapp is deployed and started
|
||||
await().atMost(Duration.ofSeconds(5)).until(() ->
|
||||
{
|
||||
Handler[] children = server.getChildHandlersByClass(WebAppContext.class);
|
||||
if (children == null || children.length == 0)
|
||||
return false;
|
||||
WebAppContext webAppContext = (WebAppContext)children[0];
|
||||
if (webAppContext.isStarted())
|
||||
return webAppContext.getContextPath();
|
||||
return null;
|
||||
}, is("/foo"));
|
||||
|
||||
String[] expectedOrderedEvents = {
|
||||
// The deepest component starts first
|
||||
"Scanner started",
|
||||
"ScanningAppProvider started",
|
||||
"Server started",
|
||||
// We should see scan events after the server has started
|
||||
"Scan Started [1]",
|
||||
"Scan Ended [1]",
|
||||
"Scan Started [2]",
|
||||
"Scan Ended [2]"
|
||||
};
|
||||
|
||||
assertThat(eventQueue.size(), is(expectedOrderedEvents.length));
|
||||
// collect string array representing ACTUAL scan events (useful for meaningful error message on failed assertion)
|
||||
String scanEventsStr = "[\"" + String.join("\", \"", eventQueue) + "\"]";
|
||||
for (int i = 0; i < expectedOrderedEvents.length; i++)
|
||||
{
|
||||
String event = eventQueue.poll(5, TimeUnit.SECONDS);
|
||||
assertThat("Expected Event [" + i + "]: " + scanEventsStr, event, is(expectedOrderedEvents[i]));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasJettyGeneratedPath(File basedir, String expectedWarFilename)
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
|||
import org.eclipse.jetty.toolchain.test.PathAssert;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.resource.PathResource;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
@ -69,46 +70,41 @@ public class XmlConfiguredJetty
|
|||
public static Server loadConfigurations(List<Resource> configurations, Map<String, String> properties)
|
||||
throws Exception
|
||||
{
|
||||
XmlConfiguration last = null;
|
||||
Object[] obj = new Object[configurations.size()];
|
||||
Map<String, Object> idMap = configure(configurations, properties);
|
||||
|
||||
// Configure everything
|
||||
for (int i = 0; i < configurations.size(); i++)
|
||||
{
|
||||
Resource config = configurations.get(i);
|
||||
XmlConfiguration configuration = new XmlConfiguration(config);
|
||||
if (last != null)
|
||||
configuration.getIdMap().putAll(last.getIdMap());
|
||||
configuration.getProperties().putAll(properties);
|
||||
obj[i] = configuration.configure();
|
||||
last = configuration;
|
||||
}
|
||||
Server server = (Server)idMap.get("Server");
|
||||
|
||||
// Test for Server Instance.
|
||||
Server foundServer = null;
|
||||
int serverCount = 0;
|
||||
for (int i = 0; i < configurations.size(); i++)
|
||||
{
|
||||
if (obj[i] instanceof Server)
|
||||
{
|
||||
if (obj[i].equals(foundServer))
|
||||
{
|
||||
// Identical server instance found
|
||||
break;
|
||||
}
|
||||
foundServer = (Server)obj[i];
|
||||
serverCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (serverCount <= 0)
|
||||
if (server == null)
|
||||
{
|
||||
throw new Exception("Load failed to configure a " + Server.class.getName());
|
||||
}
|
||||
|
||||
assertEquals(1, serverCount, "Server load count");
|
||||
return server;
|
||||
}
|
||||
|
||||
return foundServer;
|
||||
/**
|
||||
* Configure for the list of XML Resources and Properties.
|
||||
*
|
||||
* @param xmls the xml resources (in order of execution)
|
||||
* @param properties the properties to use with the XML
|
||||
* @return the ID Map of configured objects (key is the id name in the XML, and the value is configured object)
|
||||
* @throws Exception if unable to create objects or read XML
|
||||
*/
|
||||
public static Map<String, Object> configure(List<Resource> xmls, Map<String, String> properties) throws Exception
|
||||
{
|
||||
Map<String, Object> idMap = new HashMap<>();
|
||||
|
||||
// Configure everything
|
||||
for (Resource xmlResource : xmls)
|
||||
{
|
||||
XmlConfiguration configuration = new XmlConfiguration(xmlResource);
|
||||
configuration.getIdMap().putAll(idMap);
|
||||
configuration.getProperties().putAll(properties);
|
||||
configuration.configure();
|
||||
idMap.putAll(configuration.getIdMap());
|
||||
}
|
||||
|
||||
return idMap;
|
||||
}
|
||||
|
||||
public XmlConfiguredJetty(Path testdir) throws IOException
|
||||
|
@ -424,6 +420,6 @@ public class XmlConfiguredJetty
|
|||
|
||||
public void stop() throws Exception
|
||||
{
|
||||
_server.stop();
|
||||
LifeCycle.stop(_server);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
<Set name="scanInterval">1</Set>
|
||||
<Set name="tempDir"><Property name="jetty.home" default="target" />/workish</Set>
|
||||
<Set name="useRealPaths">false</Set>
|
||||
<Set name="deferInitialScan"><Property name="jetty.deploy.deferInitialScan" default="false"/></Set>
|
||||
</New>
|
||||
</Item>
|
||||
</Array>
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
#org.eclipse.jetty.deploy.DeploymentTempDirTest.LEVEL=DEBUG
|
||||
#org.eclipse.jetty.deploy.LEVEL=DEBUG
|
||||
#org.eclipse.jetty.webapp.LEVEL=DEBUG
|
||||
#org.eclipse.jetty.util.Scanner=DEBUG
|
||||
#org.eclipse.jetty.util.Scanner.LEVEL=DEBUG
|
||||
|
|
|
@ -70,6 +70,8 @@ public class Scanner extends ContainerLifeCycle
|
|||
private Map<Path, MetaData> _prevScan;
|
||||
private FilenameFilter _filter;
|
||||
private final Map<Path, IncludeExcludeSet<PathMatcher, Path>> _scannables = new ConcurrentHashMap<>();
|
||||
private boolean _autoStartScanning = true;
|
||||
private boolean _scanningStarted = false;
|
||||
private boolean _reportExisting = true;
|
||||
private boolean _reportDirs = true;
|
||||
private Scheduler.Task _task;
|
||||
|
@ -520,6 +522,36 @@ public class Scanner extends ContainerLifeCycle
|
|||
_scanDepth = scanDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if scanning should start automatically with {@code Scanner}.{@link #start()}
|
||||
*
|
||||
* @return true if scanning should start automatically, false to have scanning is deferred to a later manual call to {@link #startScanning()}
|
||||
*/
|
||||
public boolean isAutoStartScanning()
|
||||
{
|
||||
return _autoStartScanning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag to control scanning auto start feature.
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@code true} - to have scanning automatically start with the Scanner.{@link #start()}</li>
|
||||
* <li>{@code false} - to have scanning deferred until a future call to {@link #startScanning()}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* If choosing to defer the automatic scanning, a future call to {@link #startScanning()}
|
||||
* is required to initiate this Scanner so that it can begin report files in the {@link #setScanDirs(List)}
|
||||
* </p>
|
||||
*
|
||||
* @param autostart true if scanning should start automatically, false to defer start of scanning to a later call to {@link #startScanning()}
|
||||
*/
|
||||
public void setAutoStartScanning(boolean autostart)
|
||||
{
|
||||
this._autoStartScanning = autostart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not an initial scan will report all files as being
|
||||
* added.
|
||||
|
@ -587,8 +619,37 @@ public class Scanner extends ContainerLifeCycle
|
|||
public void doStart() throws Exception
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Scanner start: rprtExists={}, depth={}, rprtDirs={}, interval={}, filter={}, scannables={}",
|
||||
_reportExisting, _scanDepth, _reportDirs, _scanInterval, _filter, _scannables);
|
||||
LOG.debug("Scanner start: autoStartScanning={}, reportExists={}, depth={}, rprtDirs={}, interval={}, filter={}, scannables={}",
|
||||
isAutoStartScanning(), _reportExisting, _scanDepth, _reportDirs, _scanInterval, _filter, _scannables);
|
||||
|
||||
// Start the scanner and managed beans (eg: the scheduler)
|
||||
super.doStart();
|
||||
|
||||
if (isAutoStartScanning())
|
||||
{
|
||||
startScanning();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start scanning.
|
||||
* <p>
|
||||
* This will perform the initial scan of the directories {@link #setScanDirs(List)}
|
||||
* and schedule future scans, following all of the configuration
|
||||
* of the scan (eg: {@link #setReportExistingFilesOnStartup(boolean)})
|
||||
* </p>
|
||||
*/
|
||||
public void startScanning()
|
||||
{
|
||||
if (!isRunning())
|
||||
throw new IllegalStateException("Scanner not started");
|
||||
|
||||
if (_scanningStarted)
|
||||
return;
|
||||
_scanningStarted = true;
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{}.startup()", this.getClass().getSimpleName());
|
||||
|
||||
if (_reportExisting)
|
||||
{
|
||||
|
@ -602,9 +663,7 @@ public class Scanner extends ContainerLifeCycle
|
|||
_prevScan = scanFiles();
|
||||
}
|
||||
|
||||
super.doStart();
|
||||
|
||||
//schedule the scan
|
||||
// schedule further scans
|
||||
schedule();
|
||||
}
|
||||
|
||||
|
@ -624,6 +683,7 @@ public class Scanner extends ContainerLifeCycle
|
|||
_task = null;
|
||||
if (task != null)
|
||||
task.cancel();
|
||||
_scanningStarted = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -712,7 +772,7 @@ public class Scanner extends ContainerLifeCycle
|
|||
}
|
||||
|
||||
/**
|
||||
* Scan all of the given paths.
|
||||
* Scan all the given paths.
|
||||
*/
|
||||
private Map<Path, MetaData> scanFiles()
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue