hotswapTransformer.registerTransformer(appClassLoader, basePackage + ".*", new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
if (classBeingRedefined != null) {
scheduler.scheduleCommand(new ClassPathBeanRefreshCommand(appClassLoader,
basePackage, className, classfileBuffer));
}
return classfileBuffer;
}
});
Enumeration<URL> resourceUrls = null;
try {
resourceUrls = appClassLoader.getResources(basePackage.replace(".", "/"));
} catch (IOException e) {
LOGGER.error("Unable to resolve base package {} in classloader {}.", basePackage, appClassLoader);
return;
}
// for all application resources watch for changes
while (resourceUrls.hasMoreElements()) {
URL basePackageURL = resourceUrls.nextElement();
if (!IOUtils.isFileURL(basePackageURL)) {
LOGGER.debug("Spring basePackage '{}' - unable to watch files on URL '{}' for changes (JAR file?), limited hotswap reload support. " +
"Use extraClassPath configuration to locate class file on filesystem.", basePackage, basePackageURL);
continue;
} else {
watcher.addEventListener(appClassLoader, basePackageURL, new WatchEventListener() {
@Override
public void onEvent(WatchFileEvent event) {
if (event.isFile() && event.getURI().toString().endsWith(".class")) {
// check that the class is not loaded by the classloader yet (avoid duplicate reload)
String className;
try {
className = IOUtils.urlToClassName(event.getURI());
} catch (IOException e) {
LOGGER.trace("Watch event on resource '{}' skipped, probably Ok because of delete/create event sequence (compilation not finished yet).", e, event.getURI());
return;
}
if (!ClassLoaderHelper.isClassLoaded(appClassLoader, className)) {
// refresh spring only for new classes
scheduler.scheduleCommand(new ClassPathBeanRefreshCommand(appClassLoader,
basePackage, event), WAIT_ON_CREATE);
}
}
}
});