Index: src/main/resources/info/magnolia/cms/cache/pages/CacheToolsPage.html =================================================================== --- src/main/resources/info/magnolia/cms/cache/pages/CacheToolsPage.html (revision 0) +++ src/main/resources/info/magnolia/cms/cache/pages/CacheToolsPage.html (revision 0) @@ -0,0 +1,86 @@ + + + + Cache flushing + + + + + [#if message?exists] +
${message}
+
+ [/#if] + + +
+ +
+

Caches information

+
+ nr. of elements +
+ [#list this.cacheSizes?keys as key] +
+ ${this.cacheSizes[key]} +
+ [/#list] +
+ +
+
+
+ + +
+ +
+

Flush from caches by UUID

+
+ + +
+
+ + +
+
+ +
+
+
+ + +
+ +
+

Flush a cache by name

+
+ + +
+
+ +
+
+
+ + +
+ +
+

Flush all caches

+
+ +
+
+
+ + \ No newline at end of file Index: src/main/resources/mgnl-bootstrap/cache/config.modules.cache.commands.cache.flushNamedCache.xml =================================================================== --- src/main/resources/mgnl-bootstrap/cache/config.modules.cache.commands.cache.flushNamedCache.xml (revision 0) +++ src/main/resources/mgnl-bootstrap/cache/config.modules.cache.commands.cache.flushNamedCache.xml (revision 0) @@ -0,0 +1,32 @@ + + + + mgnl:contentNode + + + mix:lockable + + + df03cd76-c17f-484d-a6da-6551a402c9c7 + + + info.magnolia.module.cache.commands.FlushNamedCacheCommand + + + + mgnl:metaData + + + false + + + superuser + + + 2010-03-10T10:36:40.248+01:00 + + + 2010-07-30T15:28:55.046+02:00 + + + Index: src/main/resources/mgnl-bootstrap/cache/admincentral/config.modules.adminInterface.config.menu.tools.cacheTools.xml =================================================================== --- src/main/resources/mgnl-bootstrap/cache/admincentral/config.modules.adminInterface.config.menu.tools.cacheTools.xml (revision 0) +++ src/main/resources/mgnl-bootstrap/cache/admincentral/config.modules.adminInterface.config.menu.tools.cacheTools.xml (revision 0) @@ -0,0 +1,38 @@ + + + + mgnl:contentNode + + + mix:lockable + + + d0f1d02d-4a7f-4d04-859c-d8fa9afd4a83 + + + /.resources/icons/16/gears.gif + + + Cache tools + + + MgnlAdminCentral.showContent('/.magnolia/pages/cacheTools.html'); + + + + mgnl:metaData + + + false + + + superuser + + + 2010-07-20T14:30:41.953+02:00 + + + 2010-07-30T15:51:31.140+02:00 + + + Index: src/main/resources/mgnl-bootstrap/cache/config.modules.cache.pages.xml =================================================================== --- src/main/resources/mgnl-bootstrap/cache/config.modules.cache.pages.xml (revision 0) +++ src/main/resources/mgnl-bootstrap/cache/config.modules.cache.pages.xml (revision 0) @@ -0,0 +1,60 @@ + + + + mgnl:content + + + mix:lockable + + + 3112b405-1adc-4b1f-bd58-c81ea48c9717 + + + + mgnl:metaData + + + false + + + superuser + + + 2010-07-20T14:30:41.953+02:00 + + + 2010-07-30T13:17:29.812+02:00 + + + + + mgnl:contentNode + + + mix:lockable + + + 3f3027b6-e302-4b24-afdf-46622ab85a06 + + + info.magnolia.cms.cache.pages.CacheToolsPage + + + + mgnl:metaData + + + superuser + + + 2010-07-20T14:30:41.953+02:00 + + + 2010-07-30T15:31:57.531+02:00 + + + + + + + Index: src/main/java/info/magnolia/module/cache/commands/FlushNamedCacheCommand.java =================================================================== --- src/main/java/info/magnolia/module/cache/commands/FlushNamedCacheCommand.java (revision 0) +++ src/main/java/info/magnolia/module/cache/commands/FlushNamedCacheCommand.java (revision 0) @@ -0,0 +1,39 @@ +package info.magnolia.module.cache.commands; + +import info.magnolia.commands.MgnlCommand; +import info.magnolia.context.Context; +import info.magnolia.module.ModuleRegistry; +import info.magnolia.module.cache.Cache; +import info.magnolia.module.cache.CacheFactory; +import info.magnolia.module.cache.CacheModule; + +import org.apache.commons.lang.StringUtils; + +/** + * Command to flush a cache by name. + * @author bert + * + */ +public class FlushNamedCacheCommand extends MgnlCommand { + + public static final String CACHE_NAME = "cacheName"; + private final CacheModule cacheModule; + + public FlushNamedCacheCommand() { + cacheModule = ModuleRegistry.Factory.getInstance().getModuleInstance(CacheModule.class); + } + + @Override + public boolean execute(Context context) throws Exception { + String cacheName = (String) context.get(CACHE_NAME); + if(StringUtils.isNotBlank(cacheName)) { + CacheFactory factory = cacheModule.getCacheFactory(); + Cache cache = factory.getCache(cacheName); + if(cache != null) { + cache.clear(); + } + } + return true; + } + +} Index: src/main/java/info/magnolia/module/cache/FlushSubpathCacheListeningPolicy.java =================================================================== --- src/main/java/info/magnolia/module/cache/FlushSubpathCacheListeningPolicy.java (revision 0) +++ src/main/java/info/magnolia/module/cache/FlushSubpathCacheListeningPolicy.java (revision 0) @@ -0,0 +1,72 @@ +package info.magnolia.module.cache; + +import info.magnolia.cms.beans.config.ContentRepository; +import info.magnolia.cms.util.ObservationUtil; +import info.magnolia.module.cache.AbstractListeningFlushPolicy; +import info.magnolia.module.cache.Cache; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.jcr.observation.Event; +import javax.jcr.observation.EventListener; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * CachePolicy that flushes a cache when there is a change in the content of the + * repositories subpath. + * + * @author bert + */ +public class FlushSubpathCacheListeningPolicy extends AbstractListeningFlushPolicy { + Logger log = LoggerFactory.getLogger(FlushSubpathCacheListeningPolicy.class); + private final Map registeredListeners = new HashMap(); + + public void start(Cache cache) { + for (Iterator iter = getRepositories().iterator(); iter.hasNext();) { + final String repository = (String) iter.next(); + if (ContentRepository.getRepositoryMapping(repository) != null) { + final CacheCleaner cacheCleaner = new CacheCleaner(cache, repository); + final EventListener listener = ObservationUtil.instanciateDeferredEventListener(cacheCleaner, 5000, 30000); + final String path = "default".equals(cache.getName()) ? "" : cache.getName(); + try { + ObservationUtil.registerChangeListener(repository, "/" + path, listener); + } catch (Exception e) { + log.warn("Failed to register cache flushing observation for repository {} due to {}", repository, e.getMessage()); + log.warn("Publishing any content to {} will not result in update of the cache. Please flush the cache manually."); + } + registeredListeners.put(repository, listener); + } + } + } + + public void stop(Cache cache) { + final Iterator i = registeredListeners.keySet().iterator(); + while (i.hasNext()) { + final String repository = (String) i.next(); + final EventListener listener = registeredListeners.get(repository); + if (listener == null) { + // happens on restart of cache module after someone configures new listener repository ... we are trying to stop the listener which was not created yet + continue; + } + ObservationUtil.unregisterChangeListener(repository, listener); + } + } + + @Override + protected void handleSingleEvent(Cache cache, String repository, Event event) { + } + + @Override + protected void postHandleEvents(Cache cache, String repository) { + } + + @Override + protected boolean preHandleEvents(Cache cache, String repository) { + cache.clear(); + return false; + } +} Index: src/main/java/info/magnolia/cms/cache/pages/CacheToolsPage.java =================================================================== --- src/main/java/info/magnolia/cms/cache/pages/CacheToolsPage.java (revision 0) +++ src/main/java/info/magnolia/cms/cache/pages/CacheToolsPage.java (revision 0) @@ -0,0 +1,117 @@ +package info.magnolia.cms.cache.pages; + +import info.magnolia.cms.beans.config.ContentRepository; +import info.magnolia.cms.util.AlertUtil; +import info.magnolia.context.MgnlContext; +import info.magnolia.module.ModuleRegistry; +import info.magnolia.module.admininterface.TemplatedMVCHandler; +import info.magnolia.module.cache.CacheConfiguration; +import info.magnolia.module.cache.CacheFactory; +import info.magnolia.module.cache.CacheModule; +import info.magnolia.module.cache.commands.FlushCachesCommand; +import info.magnolia.module.cache.commands.FlushFromCachesByUUIDCommand; +import info.magnolia.module.cache.commands.FlushNamedCacheCommand; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Tools page to show cache info and flush caches. + * + * @author bert + */ +public class CacheToolsPage extends TemplatedMVCHandler { + + private final CacheModule cacheModule; + + public CacheToolsPage(String name, HttpServletRequest request, HttpServletResponse response) { + super(name, request, response); + cacheModule = ModuleRegistry.Factory.getInstance().getModuleInstance(CacheModule.class); + } + + public String refresh() { + return this.show(); + } + + public String flushNamedCache() { + try { + AlertUtil.setMessage(flushNamedCacheCommand()); + } + catch (Exception e) { + AlertUtil.setMessage("Error when flushing cache: " + e.getMessage(), e); + } + return this.show(); + } + + private String flushNamedCacheCommand() { + FlushNamedCacheCommand command = new FlushNamedCacheCommand(); + try { + command.execute(MgnlContext.getInstance()); + } catch (Exception e) { + return "Error occurred during command execution. (" + e.getMessage() +")"; + } + + return "Cache \"" + MgnlContext.getParameter(FlushNamedCacheCommand.CACHE_NAME) + "\" is flushed."; + } + + public String flushByUUID() { + try { + AlertUtil.setMessage(flushByUUIDCommand()); + } + catch (Exception e) { + AlertUtil.setMessage("Error when flushing by uuid: " + e.getMessage(), e); + } + return this.show(); + } + + private String flushByUUIDCommand() { + FlushFromCachesByUUIDCommand command = new FlushFromCachesByUUIDCommand(); + try { + command.execute(MgnlContext.getInstance()); + } catch (Exception e) { + return "Error occurred during command execution. (" + e.getMessage() +")"; + } + return "UUID \"" + MgnlContext.getParameter(FlushFromCachesByUUIDCommand.UUID) + "\" is flushed from cache."; + } + + public String flushAllCaches() { + try { + AlertUtil.setMessage(flushAllCacheCommand()); + } + catch (Exception e) { + AlertUtil.setMessage("Error when flushing all caches: " + e.getMessage(), e); + } + return this.show(); + } + + private String flushAllCacheCommand() { + FlushCachesCommand command = new FlushCachesCommand(); + try { + command.execute(MgnlContext.getInstance()); + } catch (Exception e) { + return "Error occurred during command execution. (" + e.getMessage() +")"; + } + return "All caches are flushed."; + } + + public Map getCacheSizes() { + Map cacheNames = new HashMap(); + CacheFactory factory = cacheModule.getCacheFactory(); + Collection cacheConfigs = cacheModule.getConfigurations().values(); + for (CacheConfiguration config : cacheConfigs) { + String cacheName = config.getName(); + cacheNames.put(cacheName, factory.getCache(cacheName).getSize()); + } + return cacheNames; + } + + public Iterator getRepositories() { + return ContentRepository.getAllRepositoryNames(); + } + +}