diff --git a/memory-impl/impl/pom.xml b/memory-impl/impl/pom.xml index 5ff2ee3..0faa726 100644 --- a/memory-impl/impl/pom.xml +++ b/memory-impl/impl/pom.xml @@ -27,6 +27,11 @@ org.sakaiproject + sakai-component-api + ${sakai.version} + + + org.sakaiproject sakai-entity-api ${sakai.version} diff --git a/memory-impl/impl/src/java/org/sakaiproject/memory/impl/BasicMemoryService.java b/memory-impl/impl/src/java/org/sakaiproject/memory/impl/BasicMemoryService.java index e386d4c..d58c8c0 100644 --- a/memory-impl/impl/src/java/org/sakaiproject/memory/impl/BasicMemoryService.java +++ b/memory-impl/impl/src/java/org/sakaiproject/memory/impl/BasicMemoryService.java @@ -39,6 +39,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.authz.api.AuthzGroupService; import org.sakaiproject.authz.api.SecurityService; +import org.sakaiproject.component.api.ServerConfigurationService; import org.sakaiproject.component.cover.ComponentManager; import org.sakaiproject.event.api.Event; import org.sakaiproject.event.api.EventTrackingService; @@ -93,7 +94,12 @@ public abstract class BasicMemoryService implements MemoryService, Observer * @return the AuthzGroupService collaborator. */ protected abstract AuthzGroupService authzGroupService(); - + + /** + * @return the ServerConfigurationService collaborator + */ + protected abstract ServerConfigurationService serverConfigurationService(); + /********************************************************************************************************************************************************************************************************************************************************** * Configuration *********************************************************************************************************************************************************************************************************************************************************/ @@ -469,10 +475,16 @@ public abstract class BasicMemoryService implements MemoryService, Observer return cacheManager.getEhcache(name); } cacheManager.addCache(name); - return cacheManager.getEhcache(name); - - + Ehcache cache = cacheManager.getEhcache(name); + // Not look for any custom configuration. + String config = serverConfigurationService().getString(name); + if (config != null && config.length() > 0) { + M_log.debug("Found configuration for cache: "+ name+ " of: "+ config); + new CacheInitializer().configure(config).initialize( + cache.getCacheConfiguration()); + } + return cache; /* diff --git a/memory-impl/impl/src/java/org/sakaiproject/memory/impl/CacheInitializer.java b/memory-impl/impl/src/java/org/sakaiproject/memory/impl/CacheInitializer.java new file mode 100644 index 0000000..ea5dd05 --- /dev/null +++ b/memory-impl/impl/src/java/org/sakaiproject/memory/impl/CacheInitializer.java @@ -0,0 +1,128 @@ +package org.sakaiproject.memory.impl; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; + +import net.sf.ehcache.config.CacheConfiguration; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Utility class to configure a cache. Could have used common beanutils but + * didn't want another library. + * + * @author buckett + * + */ +public class CacheInitializer { + + private static final Log log = LogFactory.getLog(CacheInitializer.class); + + private Map configMap; + + public CacheInitializer() { + + } + + /** + * Set the configuration that needs to be set on the cache. + * + * @param config + * The unsplit configuration. Eg: + * "timeToLiveSeconds=400,timeToIdleSeconds=100" + * @return This object. + */ + public CacheInitializer configure(String config) { + configMap = new HashMap(); + String[] configParts = config.split(","); + for (String part : configParts) { + String[] splitParts = part.split("=", 2); + if (splitParts.length == 2) { + String key = splitParts[0]; + String value = splitParts[1]; + configMap.put(key, value); + } else { + log.warn("Couldn't parse cache config of: " + part); + } + } + return this; + } + + /** + * Configure + * + * @param cacheConfig + * @return + */ + public CacheInitializer initialize(CacheConfiguration cacheConfig) { + if (configMap == null) { + throw new IllegalStateException( + "You must configure the initializer first."); + } + Method[] methods = cacheConfig.getClass().getMethods(); + for (Method method : methods) { + if (Modifier.isPublic(method.getModifiers()) + && method.getName().startsWith("set") + && method.getParameterTypes().length == 1) { + // Ok we can handle this method. + String key = Character.toLowerCase(method.getName().charAt( + "set".length())) + + method.getName().substring("set".length() + 1); + log.debug("Looking in config map for: " + key); + String value = configMap.get(key); + if (value != null) { + Class clazz = method.getParameterTypes()[0]; + log.debug("Need to convert to :" + clazz); + Object obj = covertValue(value, clazz); + + if (obj != null) { + invokeMethod(method, cacheConfig, obj); + } + + } + + } + } + return this; + } + + private Object covertValue(String value, Class clazz) { + Object obj = null; + try { + if (String.class.equals(clazz)) { + obj = value; + } else if (Integer.class.equals(clazz) || int.class.equals(clazz)) { + obj = Integer.valueOf(value); + } else if (Boolean.class.equals(clazz) + || boolean.class.equals(clazz)) { + obj = Boolean.valueOf(value); + } else if (Long.class.equals(clazz) || long.class.equals(clazz)) { + obj = Long.valueOf(value); + } else if (Float.class.equals(clazz) || float.class.equals(clazz)) { + obj = Float.valueOf(value); + } else if (Double.class.equals(clazz) || double.class.equals(clazz)) { + obj = Double.valueOf(value); + } else if (Character.class.equals(clazz) + || char.class.equals(clazz)) { + obj = Character.valueOf(value.charAt(0)); + } else { + log.debug("Can't convert to :" + clazz); + } + } catch (NumberFormatException nfe) { + log.debug("Ignored bad number: " + value); + } + return obj; + } + + private void invokeMethod(Method method, Object obj, Object value) { + try { + method.invoke(obj, value); + } catch (Exception e) { + log.debug(e); + } + } + +} diff --git a/memory-impl/impl/src/java/org/sakaiproject/memory/impl/MemoryServiceTest.java b/memory-impl/impl/src/java/org/sakaiproject/memory/impl/MemoryServiceTest.java index 05c3584..39ec259 100644 --- a/memory-impl/impl/src/java/org/sakaiproject/memory/impl/MemoryServiceTest.java +++ b/memory-impl/impl/src/java/org/sakaiproject/memory/impl/MemoryServiceTest.java @@ -23,6 +23,7 @@ package org.sakaiproject.memory.impl; import org.sakaiproject.authz.api.AuthzGroupService; import org.sakaiproject.authz.api.SecurityService; +import org.sakaiproject.component.api.ServerConfigurationService; import org.sakaiproject.event.api.EventTrackingService; import org.sakaiproject.event.api.UsageSessionService; import org.sakaiproject.memory.api.Cache; @@ -89,5 +90,11 @@ public class MemoryServiceTest extends BasicMemoryService return null; } + @Override + protected ServerConfigurationService serverConfigurationService() { + // TODO Auto-generated method stub + return null; + } + } diff --git a/memory-impl/impl/src/test/org/sakai/memory/impl/test/MemoryServiceTest.java b/memory-impl/impl/src/test/org/sakai/memory/impl/test/MemoryServiceTest.java index 190b527..79fc7b5 100644 --- a/memory-impl/impl/src/test/org/sakai/memory/impl/test/MemoryServiceTest.java +++ b/memory-impl/impl/src/test/org/sakai/memory/impl/test/MemoryServiceTest.java @@ -30,6 +30,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.authz.api.AuthzGroupService; import org.sakaiproject.authz.api.SecurityService; +import org.sakaiproject.component.api.ServerConfigurationService; import org.sakaiproject.event.api.EventTrackingService; import org.sakaiproject.event.api.UsageSessionService; import org.sakaiproject.memory.api.Cache; @@ -49,6 +50,7 @@ public class MemoryServiceTest extends TestCase private AuthzGroupService authzGroupService; private BasicMemoryService basicMemoryService; private CacheManager cacheManager; + private ServerConfigurationService serverConfigurationService; /** * @param name @@ -67,9 +69,10 @@ public class MemoryServiceTest extends TestCase eventTrackingService = new MockEventTrackingService(); securityService = new MockSecurityService(); + serverConfigurationService = new MockServerConfigurationService(); usageSessionService = new MockUsageSessionService(); authzGroupService = new MockAuthzGroupService(); - basicMemoryService = new MockBasicMemoryService(eventTrackingService, securityService, usageSessionService, authzGroupService ); + basicMemoryService = new MockBasicMemoryService(eventTrackingService, securityService, usageSessionService, authzGroupService, serverConfigurationService ); cacheManager = new CacheManager(this.getClass().getResourceAsStream("ehcache.xml")); basicMemoryService.setCacheManager(cacheManager); } diff --git a/memory-impl/impl/src/test/org/sakai/memory/impl/test/MockBasicMemoryService.java b/memory-impl/impl/src/test/org/sakai/memory/impl/test/MockBasicMemoryService.java index b6c42a7..47b8e34 100644 --- a/memory-impl/impl/src/test/org/sakai/memory/impl/test/MockBasicMemoryService.java +++ b/memory-impl/impl/src/test/org/sakai/memory/impl/test/MockBasicMemoryService.java @@ -23,6 +23,7 @@ package org.sakai.memory.impl.test; import org.sakaiproject.authz.api.AuthzGroupService; import org.sakaiproject.authz.api.SecurityService; +import org.sakaiproject.component.api.ServerConfigurationService; import org.sakaiproject.event.api.EventTrackingService; import org.sakaiproject.event.api.UsageSessionService; import org.sakaiproject.memory.impl.BasicMemoryService; @@ -38,16 +39,18 @@ public class MockBasicMemoryService extends BasicMemoryService private SecurityService securityService; private UsageSessionService usageSessionService; private AuthzGroupService authzGroupService; + private ServerConfigurationService serverConfigurationService; /** * */ - public MockBasicMemoryService(EventTrackingService eventTrackingService, SecurityService securityService, UsageSessionService usageSessionService, AuthzGroupService authzGroupService) + public MockBasicMemoryService(EventTrackingService eventTrackingService, SecurityService securityService, UsageSessionService usageSessionService, AuthzGroupService authzGroupService, ServerConfigurationService serverConfigurationService) { this.eventTrackingService = eventTrackingService; this.securityService = securityService; this.usageSessionService = usageSessionService; this.authzGroupService = authzGroupService; + this.serverConfigurationService = serverConfigurationService; } /* (non-Javadoc) @@ -83,4 +86,9 @@ public class MockBasicMemoryService extends BasicMemoryService return authzGroupService; } + @Override + protected ServerConfigurationService serverConfigurationService() { + return serverConfigurationService; + } + } diff --git a/memory-impl/impl/src/test/org/sakai/memory/impl/test/MockServerConfigurationService.java b/memory-impl/impl/src/test/org/sakai/memory/impl/test/MockServerConfigurationService.java new file mode 100644 index 0000000..5b6e228 --- /dev/null +++ b/memory-impl/impl/src/test/org/sakai/memory/impl/test/MockServerConfigurationService.java @@ -0,0 +1,136 @@ +package org.sakai.memory.impl.test; + +import java.util.List; +import java.util.Map; + +import org.sakaiproject.component.api.ServerConfigurationService; + +public class MockServerConfigurationService implements + ServerConfigurationService { + + public String getAccessPath() { + // TODO Auto-generated method stub + return null; + } + + public String getAccessUrl() { + // TODO Auto-generated method stub + return null; + } + + public boolean getBoolean(String name, boolean dflt) { + // TODO Auto-generated method stub + return false; + } + + public List getDefaultTools(String category) { + // TODO Auto-generated method stub + return null; + } + + public String getGatewaySiteId() { + // TODO Auto-generated method stub + return null; + } + + public String getHelpUrl(String helpContext) { + // TODO Auto-generated method stub + return null; + } + + public int getInt(String name, int dflt) { + // TODO Auto-generated method stub + return 0; + } + + public String getLoggedOutUrl() { + // TODO Auto-generated method stub + return null; + } + + public String getPortalUrl() { + // TODO Auto-generated method stub + return null; + } + + public String getSakaiHomePath() { + // TODO Auto-generated method stub + return null; + } + + public String getServerId() { + // TODO Auto-generated method stub + return null; + } + + public String getServerIdInstance() { + // TODO Auto-generated method stub + return null; + } + + public String getServerInstance() { + // TODO Auto-generated method stub + return null; + } + + public String getServerName() { + // TODO Auto-generated method stub + return null; + } + + public String getServerUrl() { + // TODO Auto-generated method stub + return null; + } + + public String getString(String name) { + // TODO Auto-generated method stub + return null; + } + + public String getString(String name, String dflt) { + // TODO Auto-generated method stub + return null; + } + + public String[] getStrings(String name) { + // TODO Auto-generated method stub + return null; + } + + public List getToolCategories(String category) { + // TODO Auto-generated method stub + return null; + } + + public Map> getToolCategoriesAsMap(String category) { + // TODO Auto-generated method stub + return null; + } + + public List getToolOrder(String category) { + // TODO Auto-generated method stub + return null; + } + + public Map getToolToCategoryMap(String category) { + // TODO Auto-generated method stub + return null; + } + + public String getToolUrl() { + // TODO Auto-generated method stub + return null; + } + + public List getToolsRequired(String category) { + // TODO Auto-generated method stub + return null; + } + + public String getUserHomeUrl() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/memory-impl/impl/src/test/org/sakai/memory/impl/test/TestCacheInitializer.java b/memory-impl/impl/src/test/org/sakai/memory/impl/test/TestCacheInitializer.java new file mode 100644 index 0000000..c04ac2b --- /dev/null +++ b/memory-impl/impl/src/test/org/sakai/memory/impl/test/TestCacheInitializer.java @@ -0,0 +1,49 @@ +package org.sakai.memory.impl.test; + +import org.sakaiproject.memory.impl.CacheInitializer; + +import junit.framework.TestCase; +import net.sf.ehcache.config.CacheConfiguration; + +public class TestCacheInitializer extends TestCase { + + private CacheConfiguration config; + private CacheInitializer initializer; + + public void setUp() { + config = new CacheConfiguration(); + initializer = new CacheInitializer(); + } + + public void testSingleConfig() { + initializer.configure("timeToLiveSeconds=400").initialize(config); + assertEquals(400, config.getTimeToLiveSeconds()); + } + + public void testMultipleConfig() { + initializer.configure("timeToLiveSeconds=300,timeToIdleSeconds=150") + .initialize(config); + assertEquals(300, config.getTimeToLiveSeconds()); + assertEquals(150, config.getTimeToIdleSeconds()); + } + + public void testDuplicateConfig() { + initializer.configure("timeToLiveSeconds=300,timeToIdleSeconds=150,timeToLiveSeconds=10") + .initialize(config); + assertEquals(10, config.getTimeToLiveSeconds()); + assertEquals(150, config.getTimeToIdleSeconds()); + } + + public void testBadKey() { + initializer.configure("doesNotExist=300,timeToIdleSeconds=150") + .initialize(config); + assertEquals(150, config.getTimeToIdleSeconds()); + } + + public void testBadValue() { + initializer.configure("timeToLiveSeconds=300a,timeToIdleSeconds=150") + .initialize(config); + assertEquals(150, config.getTimeToIdleSeconds()); + } + +} diff --git a/memory-impl/pack/src/webapp/WEB-INF/components.xml b/memory-impl/pack/src/webapp/WEB-INF/components.xml index 3d4e3d0..7137838 100644 --- a/memory-impl/pack/src/webapp/WEB-INF/components.xml +++ b/memory-impl/pack/src/webapp/WEB-INF/components.xml @@ -13,6 +13,7 @@ + false