use of org.hotswap.agent.watch.WatchEventListener in project HotswapAgent by HotswapProjects.
the class SpringPlugin method registerComponentScanBasePackage.
/**
* Register both hotswap transformer AND watcher - in case of new file the file is not known
* to JVM and hence no hotswap is called. The file may even exist, but until is loaded by Spring
* it will not be known by the JVM. File events are processed only if the class is not known to the
* classloader yet.
*
* @param basePackage only files in a basePackage
*/
public void registerComponentScanBasePackage(final String basePackage) {
LOGGER.info("Registering basePackage {}", basePackage);
this.registerBasePackage(basePackage);
Enumeration<URL> resourceUrls = null;
try {
resourceUrls = getResources(basePackage);
} 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, className, event), WAIT_ON_CREATE);
}
}
}
});
}
}
}
use of org.hotswap.agent.watch.WatchEventListener in project HotswapAgent by HotswapProjects.
the class WatchResourcesClassLoader method initWatchResources.
/**
* Configure new instance with urls and watcher service.
*
* @param watchResources the URLs from which to load resources
* @param watcher watcher service to register watch events
*/
public void initWatchResources(URL[] watchResources, Watcher watcher) {
// create classloader to serve resources only from watchResources URL's
this.watchResourcesClassLoader = new UrlOnlyClassLoader(watchResources);
// register watch resources - on change event each modified resource will be added to changedUrls.
for (URL resource : watchResources) {
try {
URI uri = resource.toURI();
LOGGER.debug("Watching directory '{}' for changes.", uri);
watcher.addEventListener(this, uri, new WatchEventListener() {
@Override
public void onEvent(WatchFileEvent event) {
try {
if (event.isFile() || event.isDirectory()) {
changedUrls.add(event.getURI().toURL());
LOGGER.trace("File '{}' changed and will be returned instead of original classloader equivalent.", event.getURI().toURL());
}
} catch (MalformedURLException e) {
LOGGER.error("Unexpected - cannot convert URI {} to URL.", e, event.getURI());
}
}
});
} catch (URISyntaxException e) {
LOGGER.warning("Unable to convert watchResources URL '{}' to URI. URL is skipped.", e, resource);
}
}
}
use of org.hotswap.agent.watch.WatchEventListener in project HotswapAgent by HotswapProjects.
the class AbstractNIO2Watcher method addEventListener.
@Override
public synchronized void addEventListener(ClassLoader classLoader, URI pathPrefix, WatchEventListener listener) {
File path;
try {
// check that it is regular file
// toString() is weird and solves HiarchicalUriException for URI
// like "file:./src/resources/file.txt".
path = new File(pathPrefix);
} catch (IllegalArgumentException e) {
if (!LOGGER.isLevelEnabled(Level.TRACE)) {
LOGGER.warning("Unable to watch for path {}, not a local regular file or directory.", pathPrefix);
} else {
LOGGER.trace("Unable to watch for path {} exception", e, pathPrefix);
}
return;
}
try {
addDirectory(path.toPath());
} catch (IOException e) {
if (!LOGGER.isLevelEnabled(Level.TRACE)) {
LOGGER.warning("Unable to watch for path {}, not a local regular file or directory.", pathPrefix);
} else {
LOGGER.trace("Unable to watch path with prefix '{}' for changes.", e, pathPrefix);
}
return;
}
List<WatchEventListener> list = listeners.get(Paths.get(pathPrefix));
if (list == null) {
list = new ArrayList<WatchEventListener>();
listeners.put(Paths.get(pathPrefix), list);
}
list.add(listener);
if (classLoader != null) {
classLoaderListeners.put(listener, classLoader);
}
}
use of org.hotswap.agent.watch.WatchEventListener in project HotswapAgent by HotswapProjects.
the class OwbPlugin method registerBeansXmls.
/**
* Register BeanArchive's paths to watcher. In case of new class the class file is not known
* to JVM hence no hotswap is called and therefore it must be handled by watcher.
*
* @param bdaLocations the Set of URLs of archive locations
*/
public void registerBeansXmls(Set bdaLocations) {
// for all application resources watch for changes
for (final URL beanArchiveUrl : (Set<URL>) bdaLocations) {
String beansXmlPath = beanArchiveUrl.getPath();
if (!beansXmlPath.endsWith("beans.xml")) {
LOGGER.debug("Skipping bda location: '{}' ", beanArchiveUrl);
continue;
}
final String archivePath;
if (beansXmlPath.endsWith("META-INF/beans.xml")) {
archivePath = beansXmlPath.substring(0, beansXmlPath.length() - "META-INF/beans.xml".length());
} else if (beansXmlPath.endsWith("WEB-INF/beans.xml")) {
archivePath = beansXmlPath.substring(0, beansXmlPath.length() - "beans.xml".length()) + "classes";
} else {
LOGGER.warning("Unexpected beans.xml location '{}'", beansXmlPath);
continue;
}
if (archivePath.endsWith(".jar!/")) {
LOGGER.debug("Skipping unsupported jar beans.xml location '{}'", beansXmlPath);
continue;
}
// store path for unit tests (single archive expected)
OwbPlugin.archivePath = archivePath;
try {
URL archivePathUrl = resourceNameToURL(archivePath);
if (registeredArchives.containsKey(archivePathUrl)) {
continue;
}
registeredArchives.put(archivePathUrl, beanArchiveUrl);
URI uri = archivePathUrl.toURI();
watcher.addEventListener(appClassLoader, uri, 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) || isTestEnvironment) {
// refresh weld only for new classes
LOGGER.trace("register reload command: {} ", className);
scheduler.scheduleCommand(new BeanClassRefreshCommand(appClassLoader, archivePath, beanArchiveUrl, event), WAIT_ON_CREATE);
}
}
}
});
LOGGER.info("Registered watch for path '{}' for changes.", archivePathUrl);
} catch (URISyntaxException e) {
LOGGER.error("Unable to watch path '{}' for changes.", e, archivePath);
} catch (Exception e) {
LOGGER.warning("registerBeanDeplArchivePath() exception : {}", e.getMessage());
}
}
}
use of org.hotswap.agent.watch.WatchEventListener in project HotswapAgent by HotswapProjects.
the class WatcherNIO2Test method testTargetClasses.
// ensure it works on file:/ URIs as returned by classloader
// @Test
public void testTargetClasses() throws Exception {
URI uri = new URI("file:/" + temp);
final ResultHolder resultHolder = new ResultHolder();
watcher.addEventListener(null, uri, new WatchEventListener() {
@Override
public void onEvent(WatchFileEvent event) {
assertTrue("File name", event.getURI().toString().endsWith("test.class"));
resultHolder.result = true;
}
});
File testFile = new File(uri.toURL().getFile(), "test.class");
testFile.createNewFile();
assertTrue("Event listener not called", waitForResult(resultHolder));
testFile.delete();
}
Aggregations