public DynamicTemplateParserImpl(ClasspathURLConverter converter, BindingSource bindingSource, PageSource pageSource, TemplateParser componentTemplateParser) { this.bindingSource = bindingSource; this.pageSource = pageSource; this.componentTemplateParser = componentTemplateParser; tracker = new URLChangeTracker(converter); }
public long trackResource(Resource resource) { if (tracker == null) { return fixedLastModifiedTime; } return tracker.add(resource.toURL()); }
public void checkForUpdates() { if (tracker.containsChanges()) { tracker.clear(); cache.clear(); // A typical case is that a "context:" or "asset:" binding is used with the Dynamic component's template // parameter. This causes the Asset to be converted to a Resource and parsed. However, those are invariant // bindings, so even if it is discovered that the underlying file has changed, the parsed template // is still cached inside the component. Clearing the page pool forces the page instance to be // rebuilt, which is a crude way of clearing out that data. Other alternatives exist, such as // yielding up a proxy to the DynamicTemplate that is more change-aware. pageSource.clearCache(); } }
return timestampForNonFileURL(converted); File resourceFile = toFileFromFileProtocolURL(converted); long timestamp = readTimestamp(resourceFile); long dirTimestamp = readTimestamp(dir); fileToTimestamp.put(dir, dirTimestamp);
public void forceComponentInvalidation() { changeTracker.clear(); invalidationHub.classInControlledPackageHasChanged(); }
public void checkForUpdates() { if (tracker.containsChanges()) { forceInvalidationEvent(); } }
/** * Returns the time that the specified file was last modified, possibly rounded down to the nearest second. */ private long readTimestamp(File file) { if (!file.exists()) return FILE_DOES_NOT_EXIST_TIMESTAMP; return applyGranularity(file.lastModified()); }
/** * Re-acquires the last updated timestamp for each URL and returns true if any timestamp has changed. */ public boolean containsChanges() { boolean result = false; // This code would be highly suspect if this method was expected to be invoked // concurrently, but CheckForUpdatesFilter ensures that it will be invoked // synchronously. for (Map.Entry<File, Long> entry : fileToTimestamp.entrySet()) { long newTimestamp = readTimestamp(entry.getKey()); long current = entry.getValue(); if (current == newTimestamp) continue; result = true; entry.setValue(newTimestamp); } return result; }
private void forceCacheClear() { tracker.forceChange(); source.checkForUpdates(); }
return timestampForNonFileURL(converted); File resourceFile = toFileFromFileProtocolURL(converted); long timestamp = readTimestamp(resourceFile); long dirTimestamp = readTimestamp(dir); fileToTimestamp.put(dir, dirTimestamp);
public void forceInvalidationEvent() { fireInvalidationEvent(); if (tracker != null) { tracker.clear(); } }
public void checkForUpdates() { if (tracker != null && tracker.containsChanges()) { invalidate(); } }
/** * Returns the time that the specified file was last modified, possibly rounded down to the nearest second. */ private long readTimestamp(File file) { if (!file.exists()) return FILE_DOES_NOT_EXIST_TIMESTAMP; return applyGranularity(file.lastModified()); }
/** * Re-acquires the last updated timestamp for each URL and returns true if any timestamp has changed. */ public boolean containsChanges() { boolean result = false; // This code would be highly suspect if this method was expected to be invoked // concurrently, but CheckForUpdatesFilter ensures that it will be invoked // synchronously. for (Map.Entry<File, Long> entry : fileToTimestamp.entrySet()) { long newTimestamp = readTimestamp(entry.getKey()); long current = entry.getValue(); if (current == newTimestamp) continue; result = true; entry.setValue(newTimestamp); } return result; }
@Override public synchronized void checkForUpdates() { if (instance == null || !changeTracker.containsChanges()) { return; } logger.debug("Implementation class {} has changed and will be reloaded on next use.", implementationClassName); changeTracker.clear(); loader = null; proxyFactory.clearCache(); boolean reloadNow = informInstanceOfReload(); instance = reloadNow ? createInstance() : null; }
public DynamicTemplate parseTemplate(Resource resource) { DynamicTemplate result = cache.get(resource); if (result == null) { result = doParse(resource); cache.put(resource, result); tracker.add(resource.toURL()); } return result; }
public ResourceChangeTrackerImpl(ClasspathURLConverter classpathURLConverter, @Symbol(SymbolConstants.PRODUCTION_MODE) boolean productionMode) { super(productionMode); // Use granularity of seconds (not milliseconds) since that works properly // with response headers for identifying last modified. Don't track // folder changes, just changes to actual files. tracker = productionMode ? null : new URLChangeTracker(classpathURLConverter, true, false); }
private void invalidate() { tracker.clear(); templateResources.clear(); templates.clear(); fireInvalidationEvent(); }
public synchronized void checkForUpdates() { if (changeTracker.containsChanges()) { invalidationHub.classInControlledPackageHasChanged(); } }
private long timestampForNonFileURL(URL url) { long timestamp; try { timestamp = url.openConnection().getLastModified(); } catch (IOException ex) { throw new RuntimeException(ex); } return applyGranularity(timestamp); }