Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ReloadingDataDictionary |
|
| 2.3333333333333335;2.333 |
1 | /* | |
2 | * Copyright 2007 The Kuali Foundation | |
3 | * | |
4 | * Licensed under the Educational Community License, Version 1.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at | |
7 | * | |
8 | * http://www.opensource.org/licenses/ecl1.php | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | */ | |
16 | package org.kuali.rice.kns.datadictionary; | |
17 | ||
18 | import java.io.File; | |
19 | import java.util.ArrayList; | |
20 | import java.util.List; | |
21 | ||
22 | import no.geosoft.cc.io.FileListener; | |
23 | import no.geosoft.cc.io.FileMonitor; | |
24 | ||
25 | import org.apache.commons.lang.StringUtils; | |
26 | import org.apache.commons.logging.Log; | |
27 | import org.apache.commons.logging.LogFactory; | |
28 | import org.kuali.rice.core.api.config.property.ConfigurationService; | |
29 | import org.kuali.rice.kns.service.KNSServiceLocator; | |
30 | import org.springframework.core.io.FileSystemResource; | |
31 | import org.springframework.core.io.Resource; | |
32 | ||
33 | /** | |
34 | * Extends the DataDictionary to add reloading of changed dictionary files | |
35 | * without a restart of the web container | |
36 | * | |
37 | * <p> | |
38 | * To use modify the "dataDictionaryService" spring definition | |
39 | * (KNSSpringBeans.xml) and change the constructor arg bean class from | |
40 | * "org.kuali.rice.kns.datadictionary.DataDictionary" to | |
41 | * "org.kuali.rice.kns.datadictionary.ReloadingDataDictionary" | |
42 | * </p> | |
43 | * | |
44 | * <p> | |
45 | * NOTE: For Development Purposes Only! | |
46 | * </p> | |
47 | * | |
48 | * @author Kuali Rice Team (rice.collab@kuali.org) | |
49 | */ | |
50 | public class ReloadingDataDictionary extends DataDictionary implements FileListener { | |
51 | 0 | private static final Log LOG = LogFactory.getLog(DataDictionary.class); |
52 | ||
53 | private static final String CLASS_DIR_CONFIG_PARM = "reload.data.dictionary.classes.dir"; | |
54 | private static final String SOURCE_DIR_CONFIG_PARM = "reload.data.dictionary.source.dir"; | |
55 | private static final String INTERVAL_CONFIG_PARM = "reload.data.dictionary.interval"; | |
56 | ||
57 | public ReloadingDataDictionary() { | |
58 | 0 | super(); |
59 | 0 | } |
60 | ||
61 | /** | |
62 | * After dictionary has been loaded, determine the source files and add them | |
63 | * to the monitor | |
64 | * | |
65 | * @see org.kuali.rice.kns.datadictionary.DataDictionary#parseDataDictionaryConfigurationFiles(boolean) | |
66 | */ | |
67 | @Override | |
68 | public void parseDataDictionaryConfigurationFiles(boolean allowConcurrentValidation) { | |
69 | 0 | ConfigurationService configurationService = KNSServiceLocator.getKualiConfigurationService(); |
70 | ||
71 | // class directory part of the path that should be replaced | |
72 | 0 | String classesDir = configurationService.getPropertyString(CLASS_DIR_CONFIG_PARM); |
73 | ||
74 | // source directory where dictionary files are found | |
75 | 0 | String sourceDir = configurationService.getPropertyString(SOURCE_DIR_CONFIG_PARM); |
76 | ||
77 | // interval to poll for changes in milliseconds | |
78 | 0 | int reloadInterval = Integer.parseInt(configurationService.getPropertyString(INTERVAL_CONFIG_PARM)); |
79 | ||
80 | 0 | FileMonitor dictionaryFileMonitor = new FileMonitor(reloadInterval); |
81 | ||
82 | // need to copy the configFileLocations list here because it gets | |
83 | // cleared out after processing by super | |
84 | 0 | List<String> configLocations = new ArrayList<String>(configFileLocations); |
85 | ||
86 | 0 | super.parseDataDictionaryConfigurationFiles(allowConcurrentValidation); |
87 | 0 | for (String configLocation : configLocations) { |
88 | 0 | Resource classFileResource = getFileResource(configLocation); |
89 | try { | |
90 | 0 | String filePathClassesDir = classFileResource.getFile().getAbsolutePath(); |
91 | 0 | String sourceFilePath = StringUtils.replace(filePathClassesDir, classesDir, sourceDir); |
92 | ||
93 | 0 | File dictionaryFile = new File(filePathClassesDir); |
94 | 0 | if (dictionaryFile.exists()) { |
95 | 0 | LOG.debug("Monitoring dictionary file: " + dictionaryFile.getName()); |
96 | 0 | dictionaryFileMonitor.addFile(dictionaryFile); |
97 | } | |
98 | } | |
99 | 0 | catch (Exception e) { |
100 | 0 | LOG.info("Exception in picking up dictionary file for monitoring: " + e.getMessage(), e); |
101 | 0 | } |
102 | 0 | } |
103 | ||
104 | // add the dictionary as a listener for file changes | |
105 | 0 | dictionaryFileMonitor.addListener(this); |
106 | 0 | } |
107 | ||
108 | /** | |
109 | * Call back when a dictionary file is changed. Calls the spring bean reader | |
110 | * to reload the file (which will override beans as necessary and destroy | |
111 | * singletons) and runs the indexer | |
112 | * | |
113 | * @see no.geosoft.cc.io.FileListener#fileChanged(java.io.File) | |
114 | */ | |
115 | @Override | |
116 | public void fileChanged(File file) { | |
117 | 0 | LOG.info("reloading dictionary configuration for " + file.getName()); |
118 | try { | |
119 | 0 | Resource resource = new FileSystemResource(file); |
120 | 0 | xmlReader.loadBeanDefinitions(resource); |
121 | ||
122 | // re-index | |
123 | 0 | ddIndex.run(); |
124 | } | |
125 | 0 | catch (Exception e) { |
126 | 0 | LOG.info("Exception in dictionary hot deploy: " + e.getMessage(), e); |
127 | 0 | } |
128 | 0 | } |
129 | ||
130 | } |