Index: lams_admin/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -r7e4bdc2bf0894fd7ee87454bd66297cbca8f64f8 -re0b070e11b6c51b15b0f39906c8e3536f8ac09f0 --- lams_admin/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 7e4bdc2bf0894fd7ee87454bd66297cbca8f64f8) +++ lams_admin/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision e0b070e11b6c51b15b0f39906c8e3536f8ac09f0) @@ -285,6 +285,7 @@ config.upload.file.max.size =Maximum upload size config.upload.large.file.max.size =Maximum large upload size config.upload.file.max.memory.size =Maximum memory used when uploading +config.cache.refresh =Configuration cache refresh interval (minutes) config.executable.extensions =Executable extensions config.user.inactive.timeout =Inactive user timeout config.use.cache.debug.listener =Cache debug listener Index: lams_common/src/java/org/lamsfoundation/lams/commonContext.xml =================================================================== diff -u -rbb597b8155375e6ac4dfe280f630d323b6e5e575 -re0b070e11b6c51b15b0f39906c8e3536f8ac09f0 --- lams_common/src/java/org/lamsfoundation/lams/commonContext.xml (.../commonContext.xml) (revision bb597b8155375e6ac4dfe280f630d323b6e5e575) +++ lams_common/src/java/org/lamsfoundation/lams/commonContext.xml (.../commonContext.xml) (revision e0b070e11b6c51b15b0f39906c8e3536f8ac09f0) @@ -289,6 +289,7 @@ + Index: lams_common/src/java/org/lamsfoundation/lams/config/dao/IConfigurationDAO.java =================================================================== diff -u -re136309c831c4509819e7651ce2f565747bccb57 -re0b070e11b6c51b15b0f39906c8e3536f8ac09f0 --- lams_common/src/java/org/lamsfoundation/lams/config/dao/IConfigurationDAO.java (.../IConfigurationDAO.java) (revision e136309c831c4509819e7651ce2f565747bccb57) +++ lams_common/src/java/org/lamsfoundation/lams/config/dao/IConfigurationDAO.java (.../IConfigurationDAO.java) (revision e0b070e11b6c51b15b0f39906c8e3536f8ac09f0) @@ -27,15 +27,14 @@ import org.lamsfoundation.lams.config.ConfigurationItem; - /** * * @author Mitchell Seaton * */ -public interface IConfigurationDAO -{ +public interface IConfigurationDAO { - public List getAllItems(); + public List getAllItems(); + public ConfigurationItem getConfigItemByKey(final String configKey); -} +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/config/dao/hibernate/ConfigurationDAO.java =================================================================== diff -u -r7248fb9335792be231dcc498f37b28ffa0c794dc -re0b070e11b6c51b15b0f39906c8e3536f8ac09f0 --- lams_common/src/java/org/lamsfoundation/lams/config/dao/hibernate/ConfigurationDAO.java (.../ConfigurationDAO.java) (revision 7248fb9335792be231dcc498f37b28ffa0c794dc) +++ lams_common/src/java/org/lamsfoundation/lams/config/dao/hibernate/ConfigurationDAO.java (.../ConfigurationDAO.java) (revision e0b070e11b6c51b15b0f39906c8e3536f8ac09f0) @@ -32,42 +32,35 @@ import org.lamsfoundation.lams.dao.hibernate.BaseDAO; import org.springframework.orm.hibernate3.HibernateCallback; - /** * * @author Mitchell Seaton * */ -public class ConfigurationDAO extends BaseDAO implements IConfigurationDAO -{ - private static final String LOAD_CONFIG_ITEM_BY_KEY = "from configuration in class " + ConfigurationItem.class.getName() - + " where configuration.key=:key"; - - +public class ConfigurationDAO extends BaseDAO implements IConfigurationDAO { + private static final String LOAD_CONFIG_ITEM_BY_KEY = "from configuration in class " + + ConfigurationItem.class.getName() + " where configuration.key=:key"; + /** * @see org.lamsfoundation.lams.config.dao.IConfigurationlDAO#getAllItems() */ - - public List getAllItems(){ - return super.findAll(ConfigurationItem.class); + @Override + @SuppressWarnings("unchecked") + public List getAllItems() { + return super.findAll(ConfigurationItem.class); } - + /** * @see org.lamsfoundation.lams.config.dao.IConfigurationlDAO#getConfigItemByKey() */ - - public ConfigurationItem getConfigItemByKey(final String configKey) - { - return (ConfigurationItem) getHibernateTemplate().execute(new HibernateCallback() - { - public Object doInHibernate(Session session) throws HibernateException - { - return session.createQuery(LOAD_CONFIG_ITEM_BY_KEY) - .setString("key",configKey) - .uniqueResult(); - } - }); + @Override + public ConfigurationItem getConfigItemByKey(final String configKey) { + return (ConfigurationItem) getHibernateTemplate().execute(new HibernateCallback() { + @Override + public Object doInHibernate(Session session) throws HibernateException { + return session.createQuery(ConfigurationDAO.LOAD_CONFIG_ITEM_BY_KEY).setString("key", configKey) + .uniqueResult(); + } + }); } - - -} +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch02040029.sql =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch02040029.sql (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch02040029.sql (revision e0b070e11b6c51b15b0f39906c8e3536f8ac09f0) @@ -0,0 +1,10 @@ +SET AUTOCOMMIT = 0; +set FOREIGN_KEY_CHECKS = 0; + +-- LDEV-3254 Allow periodic update of configuration cache +insert into lams_configuration (config_key, config_value, description_key, header_name, format, required) +values ('ConfigCacheRefresInterval', 0, 'config.cache.refresh', 'config.header.system', 'LONG', 0); + +COMMIT; +SET AUTOCOMMIT = 1; +set FOREIGN_KEY_CHECKS = 1; \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/events/ResendMessagesJob.java =================================================================== diff -u -r1edbb81f16cedfcc1326e4eca6e520b5b48cbddc -re0b070e11b6c51b15b0f39906c8e3536f8ac09f0 --- lams_common/src/java/org/lamsfoundation/lams/events/ResendMessagesJob.java (.../ResendMessagesJob.java) (revision 1edbb81f16cedfcc1326e4eca6e520b5b48cbddc) +++ lams_common/src/java/org/lamsfoundation/lams/events/ResendMessagesJob.java (.../ResendMessagesJob.java) (revision e0b070e11b6c51b15b0f39906c8e3536f8ac09f0) @@ -2,6 +2,7 @@ import java.util.List; +import org.apache.log4j.Logger; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.util.MessageService; import org.quartz.JobExecutionContext; @@ -16,6 +17,8 @@ * */ public class ResendMessagesJob extends QuartzJobBean { + protected static final Logger log = Logger.getLogger(ResendMessagesJob.class); + /** * Period after which the thread gives up on attempting to resend messages. Currently - 2 days. */ @@ -69,7 +72,8 @@ ResendMessagesJob.notificationService.saveEvent(event); } } catch (Exception e) { - throw new JobExecutionException(e.getMessage()); + log.error("Error while resending messages", e); + throw new JobExecutionException("Error while resending messages"); } } } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/util/Configuration.java =================================================================== diff -u -r929b2b7bb8a93a948b76d2dad9eae5e97ab69f5b -re0b070e11b6c51b15b0f39906c8e3536f8ac09f0 --- lams_common/src/java/org/lamsfoundation/lams/util/Configuration.java (.../Configuration.java) (revision 929b2b7bb8a93a948b76d2dad9eae5e97ab69f5b) +++ lams_common/src/java/org/lamsfoundation/lams/util/Configuration.java (.../Configuration.java) (revision e0b070e11b6c51b15b0f39906c8e3536f8ac09f0) @@ -39,6 +39,10 @@ import org.lamsfoundation.lams.config.dao.hibernate.ConfigurationDAO; import org.lamsfoundation.lams.config.dao.hibernate.RegistrationDAO; import org.lamsfoundation.lams.usermanagement.WorkspaceFolder; +import org.quartz.JobDetail; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.SimpleTrigger; import org.springframework.beans.factory.InitializingBean; /** @@ -50,172 +54,187 @@ */ public class Configuration implements InitializingBean { - protected Logger log = Logger.getLogger(Configuration.class); + protected static Logger log = Logger.getLogger(Configuration.class); public static String CONFIGURATION_HELP_PAGE = "LAMS+Configuration"; - - private static Map items = null; - - protected ConfigurationDAO configurationDAO; - - protected static RegistrationDAO registrationDAO; - - protected MessageService messageService; - public static final int ITEMS_ALL = 1; - public static final int ITEMS_NON_LDAP = 2; - public static final int ITEMS_ONLY_LDAP = 3; - /** - * @param configurationDAO - * The configurationDAO to set. - */ - public void setConfigurationDAO(ConfigurationDAO configurationDAO) { - this.configurationDAO = configurationDAO; + private static Map items = null; + + protected static ConfigurationDAO configurationDAO; + protected static RegistrationDAO registrationDAO; + protected static MessageService messageService; + protected static Scheduler scheduler; + + public static String get(String key) { + if ((Configuration.items != null) && (Configuration.items.get(key) != null)) { + if (Configuration.getItemValue(Configuration.items.get(key)) != null) { + return Configuration.getItemValue(Configuration.items.get(key)); + } + } + return null; } - public void afterPropertiesSet() { - if (items != null) { - return; + public static Map getAll() { + return Configuration.items; + } + + public static boolean getAsBoolean(String key) { + if ((Configuration.items != null) && (Configuration.items.get(key) != null)) { + if (Configuration.getItemValue(Configuration.items.get(key)) != null) { + return new Boolean(Configuration.getItemValue(Configuration.items.get(key))).booleanValue(); + } } + return false; + } - Map itemsmap = Collections.synchronizedMap(new LinkedHashMap()); + public static int getAsInt(String key) { + if ((Configuration.items != null) && (Configuration.items.get(key) != null)) { + // could throw NumberFormatException which is a RuntimeException + if (Configuration.getItemValue(Configuration.items.get(key)) != null) { + return new Integer(Configuration.getItemValue(Configuration.items.get(key))).intValue(); + } + } + return -1; + } + public static String getItemValue(Object obj) { + ConfigurationItem item = (ConfigurationItem) obj; + if (item.getValue() != null) { + return item.getValue().trim(); + } + return null; + } + + public static Registration getRegistration() { + return Configuration.registrationDAO.get(); + } + + public static void refreshCache() { + Map itemMap = Collections + .synchronizedMap(new LinkedHashMap()); + try { - List mapitems = getAllItems(); + List itemList = Configuration.getAllItems(); - if (mapitems.size() > 0) { - Iterator it = mapitems.iterator(); - while (it.hasNext()) { - ConfigurationItem item = (ConfigurationItem) it.next(); + if (itemList.size() > 0) { + Iterator itemIterator = itemList.iterator(); + while (itemIterator.hasNext()) { + ConfigurationItem item = itemIterator.next(); // init ssl truststore path and password if (StringUtils.equals(item.getKey(), ConfigurationKeys.TRUSTSTORE_PATH)) { - setSystemProperty(item.getKey(), item.getValue()); + Configuration.setSystemProperty(item.getKey(), item.getValue()); } else if (StringUtils.equals(item.getKey(), ConfigurationKeys.TRUSTSTORE_PASSWORD)) { - setSystemProperty(item.getKey(), item.getValue()); + Configuration.setSystemProperty(item.getKey(), item.getValue()); } - itemsmap.put(item.getKey(), item); + itemMap.put(item.getKey(), item); } } - items = itemsmap; + Configuration.items = itemMap; + if (Configuration.log.isDebugEnabled()) { + Configuration.log.debug("Configuration cache refreshed"); + } } catch (Exception e) { - log.error("Exception has occurred: ", e); + Configuration.log.error("Exception while refreshing Configuration cache", e); } } - public List getAllItems() { - return configurationDAO.getAllItems(); + public static void saveOrUpdateRegistration(Registration reg) { + Configuration.registrationDAO.saveOrUpdate(reg); } - public static Map getAll() { - return items; - } - - public ConfigurationItem getConfigItemByKey(String key) { - if ((items != null) && (items.get(key) != null)) - if (items.get(key) != null) - return (ConfigurationItem) items.get(key); - return null; - } - - public static String getItemValue(Object obj) { - ConfigurationItem item = (ConfigurationItem) obj; - if (item.getValue() != null) - return item.getValue().trim(); - return null; - } - public static void setItemValue(Object obj, String value) { ConfigurationItem item = (ConfigurationItem) obj; item.setValue(value); } - public static String get(String key) { - if ((items != null) && (items.get(key) != null)) - if (getItemValue(items.get(key)) != null) - return getItemValue(items.get(key)); - return null; - } - - public static int getAsInt(String key) { - if ((items != null) && (items.get(key) != null)) - // could throw NumberFormatException which is a RuntimeException - if (getItemValue(items.get(key)) != null) - return new Integer(getItemValue(items.get(key))).intValue(); - return -1; - } - - public static boolean getAsBoolean(String key) { - if ((items != null) && (items.get(key) != null)) - if (getItemValue(items.get(key)) != null) - return new Boolean(getItemValue(items.get(key))).booleanValue(); - return false; - } - public static void updateItem(String key, String value) { - if (value != null) + if (value != null) { value = value.trim(); - if (items.containsKey(key)) - setItemValue(items.get(key), value); - } - - public void persistUpdate() { - // update ssl truststore path and password - setSystemProperty(ConfigurationKeys.TRUSTSTORE_PATH, get(ConfigurationKeys.TRUSTSTORE_PATH)); - setSystemProperty(ConfigurationKeys.TRUSTSTORE_PASSWORD, get(ConfigurationKeys.TRUSTSTORE_PASSWORD)); - updatePublicFolderName(); - configurationDAO.insertOrUpdateAll(items.values()); - } - - private void updatePublicFolderName() { - // LDEV-2430 update public folder name according to default server locale - WorkspaceFolder publicFolder = null; - List list = configurationDAO.findByProperty(WorkspaceFolder.class, "workspaceFolderType", - WorkspaceFolder.PUBLIC_SEQUENCES); - - if (list != null && list.size() > 0) { - publicFolder = (WorkspaceFolder) list.get(0); - String[] langCountry = LanguageUtil.getDefaultLangCountry(); - Locale locale = new Locale(langCountry[0], langCountry[1]); - publicFolder.setName(messageService.getMessageSource().getMessage("public.folder.name", null, locale)); - configurationDAO.update(publicFolder); } + if (Configuration.items.containsKey(key)) { + Configuration.setItemValue(Configuration.items.get(key), value); + } } - public String toString() { - return "Configuration items:" + (items != null ? items.toString() : "none"); + private static List getAllItems() { + return Configuration.configurationDAO.getAllItems(); } // update jvm system property - private void setSystemProperty(String key, String value) { + private static void setSystemProperty(String key, String value) { if (StringUtils.isBlank(key)) { // use default System.clearProperty(key); } else { System.setProperty(key, value); } } - + + @Override + public void afterPropertiesSet() { + if (Configuration.items != null) { + return; + } + Configuration.refreshCache(); + if (Configuration.items == null) { + return; + } + + String refreshCacheIntervalString = Configuration.get(ConfigurationKeys.CONFIGURATION_CACHE_REFRESH_INTERVAL); + Long refreshCacheInterval = StringUtils.isBlank(refreshCacheIntervalString) ? null : Long + .valueOf(refreshCacheIntervalString); + if ((refreshCacheInterval != null) && (refreshCacheInterval > 0)) { + SimpleTrigger trigger = new SimpleTrigger("configurationCacheRefreshTrigger", null); + trigger.setVolatility(true); + trigger.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY); + trigger.setRepeatInterval(Long.valueOf(refreshCacheInterval) * 60 * 1000); + + JobDetail jobDetail = new JobDetail("configurationCacheRefresh", null, ConfigurationRefreshCacheJob.class); + // do not store in DB as the job will be recreated after LAMS restart anyway + jobDetail.setVolatility(true); + + try { + Configuration.scheduler.scheduleJob(jobDetail, trigger); + } catch (SchedulerException e) { + Configuration.log + .error("Error while scheduling Configuration cache refresh. The cache will NOT be periodically updated.", + e); + } + } + } + /** + * Get contents of lams_configuration and group them using header names as key. Includes ldap items. + * + * @return + */ + public HashMap> arrangeItems() { + return arrangeItems(Configuration.ITEMS_ALL); + } + + /** * Get contents of lams_configuration and group them using header names as key. - * @param filter ITEMS_ALL: include all items; ITEMS_NON_LDAP: include non-ldap items only; - * ITEMS_ONLY_LDAP: include ldap-only items. + * + * @param filter + * ITEMS_ALL: include all items; ITEMS_NON_LDAP: include non-ldap items only; ITEMS_ONLY_LDAP: include + * ldap-only items. * @return */ public HashMap> arrangeItems(int filter) { - List originalList = getAllItems(); + List originalList = Configuration.getAllItems(); HashMap> groupedList = new HashMap>(); for (int i = 0; i < originalList.size(); i++) { - ConfigurationItem item = (ConfigurationItem) originalList.get(i); + ConfigurationItem item = originalList.get(i); String header = item.getHeaderName(); - + switch (filter) { case ITEMS_ALL: // all items included @@ -235,48 +254,84 @@ default: break; } - + if (!groupedList.containsKey(header)) { groupedList.put(header, new ArrayList()); } ArrayList currentList = groupedList.get(header); currentList.add(item); groupedList.put(header, currentList); } - + return groupedList; } - - /** - * Get contents of lams_configuration and group them using header names as key. Includes ldap - * items. - * @return - */ - public HashMap> arrangeItems() { - return arrangeItems(ITEMS_ALL); + + public ConfigurationItem getConfigItemByKey(String key) { + if ((Configuration.items != null) && (Configuration.items.get(key) != null)) { + if (Configuration.items.get(key) != null) { + return Configuration.items.get(key); + } + } + return null; } - - public static void saveOrUpdateRegistration(Registration reg){ - registrationDAO.saveOrUpdate(reg); + + public MessageService getMessageService() { + return Configuration.messageService; } - - public static Registration getRegistration(){ - return registrationDAO.get(); - } public RegistrationDAO getRegistrationDAO() { - return registrationDAO; + return Configuration.registrationDAO; } - public void setRegistrationDAO(RegistrationDAO registrationDAO) { - this.registrationDAO = registrationDAO; + public void persistUpdate() { + // update ssl truststore path and password + Configuration.setSystemProperty(ConfigurationKeys.TRUSTSTORE_PATH, + Configuration.get(ConfigurationKeys.TRUSTSTORE_PATH)); + Configuration.setSystemProperty(ConfigurationKeys.TRUSTSTORE_PASSWORD, + Configuration.get(ConfigurationKeys.TRUSTSTORE_PASSWORD)); + updatePublicFolderName(); + Configuration.configurationDAO.insertOrUpdateAll(Configuration.items.values()); } - public MessageService getMessageService() { - return messageService; + /** + * @param configurationDAO + * The configurationDAO to set. + */ + public void setConfigurationDAO(ConfigurationDAO configurationDAO) { + Configuration.configurationDAO = configurationDAO; } public void setMessageService(MessageService messageService) { - this.messageService = messageService; + Configuration.messageService = messageService; } -} + + public void setRegistrationDAO(RegistrationDAO registrationDAO) { + Configuration.registrationDAO = registrationDAO; + } + + public void setScheduler(Scheduler scheduler) { + Configuration.scheduler = scheduler; + } + + @Override + public String toString() { + return "Configuration items:" + (Configuration.items != null ? Configuration.items.toString() : "none"); + } + + @SuppressWarnings("unchecked") + private void updatePublicFolderName() { + // LDEV-2430 update public folder name according to default server locale + WorkspaceFolder publicFolder = null; + List list = Configuration.configurationDAO.findByProperty(WorkspaceFolder.class, + "workspaceFolderType", WorkspaceFolder.PUBLIC_SEQUENCES); + + if ((list != null) && (list.size() > 0)) { + publicFolder = list.get(0); + String[] langCountry = LanguageUtil.getDefaultLangCountry(); + Locale locale = new Locale(langCountry[0], langCountry[1]); + publicFolder.setName(Configuration.messageService.getMessageSource().getMessage("public.folder.name", null, + locale)); + Configuration.configurationDAO.update(publicFolder); + } + } +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java =================================================================== diff -u -rbffa8b2fb1fb58faf9e15e24aae8f0d58313de3f -re0b070e11b6c51b15b0f39906c8e3536f8ac09f0 --- lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java (.../ConfigurationKeys.java) (revision bffa8b2fb1fb58faf9e15e24aae8f0d58313de3f) +++ lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java (.../ConfigurationKeys.java) (revision e0b070e11b6c51b15b0f39906c8e3536f8ac09f0) @@ -285,4 +285,7 @@ // CNG-26 Add to lams_configuration and set to false // if you don't want imported LD to have __ appended public static String SUFFIX_IMPORTED_LD = "SuffixImportedLD"; + + // LDEV-3254 + public static String CONFIGURATION_CACHE_REFRESH_INTERVAL = "ConfigCacheRefresInterval"; } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationRefreshCacheJob.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationRefreshCacheJob.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationRefreshCacheJob.java (revision e0b070e11b6c51b15b0f39906c8e3536f8ac09f0) @@ -0,0 +1,38 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ +/* $$Id$$ */ +package org.lamsfoundation.lams.util; + +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.scheduling.quartz.QuartzJobBean; + +/** + * Refreshes configuration cache. + */ +public class ConfigurationRefreshCacheJob extends QuartzJobBean { + @Override + protected void executeInternal(JobExecutionContext context) throws JobExecutionException { + Configuration.refreshCache(); + } +} \ No newline at end of file