diff --git a/azkaban-common/src/main/java/azkaban/project/validator/XmlValidatorManager.java b/azkaban-common/src/main/java/azkaban/project/validator/XmlValidatorManager.java
index dc05c1a..5d50ef5 100644
--- a/azkaban-common/src/main/java/azkaban/project/validator/XmlValidatorManager.java
+++ b/azkaban-common/src/main/java/azkaban/project/validator/XmlValidatorManager.java
@@ -7,6 +7,7 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -52,6 +53,8 @@ public class XmlValidatorManager implements ValidatorManager {
public static final String DEFAULT_VALIDATOR_KEY = "Directory Flow";
private Map<String, ProjectValidator> validators;
+ private Map<String, Long> resourceTimestamps;
+ private String validatorDirPath;
private ClassLoader validatorLoader;
/**
@@ -62,18 +65,20 @@ public class XmlValidatorManager implements ValidatorManager {
* @param props
*/
public XmlValidatorManager(Props props) {
- String validatorDirPath = props.getString(VALIDATOR_PLUGIN_DIR, DEFAULT_VALIDATOR_DIR);
+ validatorDirPath = props.getString(VALIDATOR_PLUGIN_DIR, DEFAULT_VALIDATOR_DIR);
File validatorDir = new File(validatorDirPath);
if (!validatorDir.canRead() || !validatorDir.isDirectory()) {
throw new ValidatorManagerException("Validator directory " + validatorDirPath
+ " does not exist or is not a directory.");
}
+ resourceTimestamps = new HashMap<String, Long>();
List<URL> resources = new ArrayList<URL>();
try {
logger.info("Adding validator resources.");
for (File f : validatorDir.listFiles()) {
if (f.getName().endsWith(".jar")) {
+ resourceTimestamps.put(f.getName(), f.lastModified());
resources.add(f.toURI().toURL());
logger.debug("adding to classpath " + f.toURI().toURL());
}
@@ -92,6 +97,30 @@ public class XmlValidatorManager implements ValidatorManager {
}
}
+ private void checkResources() {
+ File validatorDir = new File(validatorDirPath);
+ List<URL> resources = new ArrayList<URL>();
+ boolean reloadResources = false;
+ try {
+ for (File f : validatorDir.listFiles()) {
+ if (f.getName().endsWith(".jar")) {
+ resources.add(f.toURI().toURL());
+ if (resourceTimestamps.get(f.getName()) != f.lastModified()) {
+ reloadResources = true;
+ logger.info("Resource " + f.getName() + " is updated. Reload the classloader.");
+ resourceTimestamps.put(f.getName(), f.lastModified());
+ }
+ }
+ }
+ } catch (MalformedURLException e) {
+ throw new ValidatorManagerException(e);
+ }
+
+ if (reloadResources) {
+ validatorLoader = new URLClassLoader(resources.toArray(new URL[resources.size()]));
+ }
+ }
+
/**
* Instances of the validators are created here rather than in the constructors. This is because
* some validators might need to maintain project-specific states, such as {@link DirectoryFlowLoader}.
@@ -119,6 +148,9 @@ public class XmlValidatorManager implements ValidatorManager {
return;
}
+ // Check for updated validator JAR files
+ checkResources();
+
// Creating the document builder to parse xml.
DocumentBuilderFactory docBuilderFactory =
DocumentBuilderFactory.newInstance();