in runner-starter/src/main/java/org/apache/apisix/plugin/runner/HotReloadProcess.java [103:178]
private void hotReloadFilter() {
if (!enableHotReload) {
cancelHotReload("hotReloadFilter");
return;
}
final BeanDefinitionRegistry registry = (BeanDefinitionRegistry) ctx.getAutowireCapableBeanFactory();
String userDir = System.getProperty("user.dir");
userDir = userDir.substring(0, userDir.lastIndexOf("apisix-java-plugin-runner") + 25);
String workDir = userDir + loadPath;
Path path = Paths.get(workDir);
boolean exists = Files.exists(path);
if (!exists) {
logger.warn("The filter workdir for hot reload {} not exists", workDir);
cancelHotReload("hotReloadFilter");
return;
}
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
path.register(watchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
watchService.close();
} catch (IOException e) {
logger.error(e.getMessage());
}
}));
while (true) {
final WatchKey key = watchService.take();
for (WatchEvent<?> watchEvent : key.pollEvents()) {
final WatchEvent.Kind<?> kind = watchEvent.kind();
final String filterFile = watchEvent.context().toString();
// ignore the file that is not java file
if (!filterFile.endsWith(".java")) {
continue;
}
String filterName = filterFile.substring(0, filterFile.length() - 5);
String filterBean = Character.toLowerCase(filterFile.charAt(0)) + filterName.substring(1);
final String filePath = workDir + filterFile;
if (kind == ENTRY_CREATE) {
logger.info("file create: {}", filePath);
BeanDefinitionBuilder builder = compile(userDir, filterName, filePath);
registry.registerBeanDefinition(filterBean, builder.getBeanDefinition());
} else if (kind == ENTRY_MODIFY) {
logger.info("file modify: {}", filePath);
registry.removeBeanDefinition(filterBean);
BeanDefinitionBuilder builder = compile(userDir, filterName, filePath);
registry.registerBeanDefinition(filterBean, builder.getBeanDefinition());
} else if (kind == ENTRY_DELETE) {
if (registry.containsBeanDefinition(filterBean)) {
logger.info("file delete: {}, and remove filter: {} ", filePath, filterBean);
registry.removeBeanDefinition(filterBean);
/*TODO: we need to remove the filter from the filter chain
* by remove the conf token in cache or other way
* */
}
} else {
logger.warn("unknown event: {}", kind);
}
}
boolean valid = key.reset();
if (!valid) {
logger.warn("key is invalid");
}
}
} catch (IOException | InterruptedException | ClassNotFoundException e) {
logger.error("watch error", e);
throw new RuntimeException(e);
}
}