001/** 002 * Copyright 2005-2016 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.krad.config; 017 018import org.kuali.rice.core.api.config.module.RunMode; 019import org.kuali.rice.core.api.config.property.ConfigContext; 020import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader; 021import org.kuali.rice.core.framework.config.module.ModuleConfigurer; 022import org.kuali.rice.krad.service.DataDictionaryService; 023import org.kuali.rice.krad.service.KRADServiceLocatorInternal; 024import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 025import org.kuali.rice.krad.util.KRADConstants; 026import org.springframework.context.ApplicationEvent; 027import org.springframework.context.ApplicationListener; 028import org.springframework.context.event.ContextRefreshedEvent; 029import org.springframework.context.event.SmartApplicationListener; 030 031import javax.sql.DataSource; 032import java.util.ArrayList; 033import java.util.Arrays; 034import java.util.List; 035import java.util.concurrent.Executors; 036import java.util.concurrent.ScheduledExecutorService; 037import java.util.concurrent.TimeUnit; 038 039public class KRADConfigurer extends ModuleConfigurer implements SmartApplicationListener { 040 041 private DataSource applicationDataSource; 042 043 private boolean includeKnsSpringBeans; 044 045 private static final String KRAD_SPRING_BEANS_PATH = "classpath:org/kuali/rice/krad/config/KRADSpringBeans.xml"; 046 private static final String KNS_SPRING_BEANS_PATH = "classpath:org/kuali/rice/kns/config/KNSSpringBeans.xml"; 047 048 public KRADConfigurer() { 049 // TODO really the constant value should be "krad" but there's some work to do in order to make 050 // that really work, see KULRICE-6532 051 super(KRADConstants.KR_MODULE_NAME); 052 setValidRunModes(Arrays.asList(RunMode.LOCAL)); 053 setIncludeKnsSpringBeans(true); 054 } 055 056 @Override 057 public void addAdditonalToConfig() { 058 configureDataSource(); 059 } 060 061 @Override 062 public List<String> getPrimarySpringFiles() { 063 final List<String> springFileLocations = new ArrayList<String>(); 064 springFileLocations.add(KRAD_SPRING_BEANS_PATH); 065 066 if (isIncludeKnsSpringBeans()) { 067 springFileLocations.add(KNS_SPRING_BEANS_PATH); 068 } 069 070 return springFileLocations; 071 } 072 073 @Override 074 public void onApplicationEvent(ApplicationEvent applicationEvent) { 075 if (applicationEvent instanceof ContextRefreshedEvent) { 076 loadDataDictionary(); 077 publishDataDictionaryComponents(); 078 } 079 } 080 081 @Override 082 public boolean supportsEventType(Class<? extends ApplicationEvent> aClass) { 083 return true; 084 } 085 086 @Override 087 public boolean supportsSourceType(Class<?> aClass) { 088 return true; 089 } 090 091 @Override 092 public int getOrder() { 093 // return a lower value which will give the data dictionary indexing higher precedence since DD indexing should 094 // be started as soon as it can be 095 return -1000; 096 } 097 098 /** 099 * Used to "poke" the Data Dictionary again after the Spring Context is initialized. This is to 100 * allow for modules loaded with KualiModule after the KNS has already been initialized to work. 101 * 102 * Also initializes the DateTimeService 103 */ 104 protected void loadDataDictionary() { 105 if (isLoadDataDictionary()) { 106 LOG.info("KRAD Configurer - Loading DD"); 107 DataDictionaryService dds = KRADServiceLocatorWeb.getDataDictionaryService(); 108 if (dds == null) { 109 dds = (DataDictionaryService) GlobalResourceLoader 110 .getService(KRADServiceLocatorWeb.DATA_DICTIONARY_SERVICE); 111 } 112 dds.getDataDictionary().parseDataDictionaryConfigurationFiles(false); 113 114 if (isValidateDataDictionary()) { 115 LOG.info("KRAD Configurer - Validating DD"); 116 dds.getDataDictionary().validateDD(isValidateDataDictionaryEboReferences()); 117 } 118 119 // KULRICE-4513 After the Data Dictionary is loaded and validated, perform Data Dictionary bean overrides. 120 dds.getDataDictionary().performBeanOverrides(); 121 } 122 } 123 124 protected void publishDataDictionaryComponents() { 125 if (isComponentPublishingEnabled()) { 126 long delay = getComponentPublishingDelay(); 127 LOG.info("Publishing of Data Dictionary components is enabled, scheduling publish after " + delay + " millisecond delay"); 128 ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); 129 try { 130 scheduler.schedule(new Runnable() { 131 @Override 132 public void run() { 133 long start = System.currentTimeMillis(); 134 LOG.info("Executing scheduled Data Dictionary component publishing..."); 135 try { 136 KRADServiceLocatorInternal.getDataDictionaryComponentPublisherService().publishAllComponents(); 137 } catch (RuntimeException e) { 138 LOG.error("Failed to publish data dictionary components.", e); 139 throw e; 140 } finally { 141 long end = System.currentTimeMillis(); 142 LOG.info("... finished scheduled execution of Data Dictionary component publishing. Took " + (end-start) + " milliseconds"); 143 } 144 } 145 }, delay, TimeUnit.MILLISECONDS); 146 } finally { 147 scheduler.shutdown(); 148 } 149 } 150 } 151 152 @Override 153 public boolean hasWebInterface() { 154 return true; 155 } 156 157 /** 158 * Returns true - KNS UI should always be included. 159 * 160 * @see org.kuali.rice.core.framework.config.module.ModuleConfigurer#shouldRenderWebInterface() 161 */ 162 @Override 163 public boolean shouldRenderWebInterface() { 164 return true; 165 } 166 167 168 169 public boolean isLoadDataDictionary() { 170 return ConfigContext.getCurrentContextConfig().getBooleanProperty("load.data.dictionary", true); 171 } 172 173 public boolean isValidateDataDictionary() { 174 return ConfigContext.getCurrentContextConfig().getBooleanProperty("validate.data.dictionary", false); 175 } 176 177 public boolean isValidateDataDictionaryEboReferences() { 178 return ConfigContext.getCurrentContextConfig().getBooleanProperty("validate.data.dictionary.ebo.references", 179 false); 180 } 181 182 public boolean isComponentPublishingEnabled() { 183 return ConfigContext.getCurrentContextConfig().getBooleanProperty( 184 KRADConstants.Config.COMPONENT_PUBLISHING_ENABLED, false); 185 } 186 187 public long getComponentPublishingDelay() { 188 return ConfigContext.getCurrentContextConfig().getNumericProperty(KRADConstants.Config.COMPONENT_PUBLISHING_DELAY, 0); 189 } 190 191 /** 192 * Used to "poke" the Data Dictionary again after the Spring Context is initialized. This is to 193 * allow for modules loaded with KualiModule after the KNS has already been initialized to work. 194 * 195 * Also initializes the DateTimeService 196 */ 197 protected void configureDataSource() { 198 if (getApplicationDataSource() != null) { 199 ConfigContext.getCurrentContextConfig() 200 .putObject(KRADConstants.KRAD_APPLICATION_DATASOURCE, getApplicationDataSource()); 201 } 202 } 203 204 public DataSource getApplicationDataSource() { 205 return this.applicationDataSource; 206 } 207 208 public void setApplicationDataSource(DataSource applicationDataSource) { 209 this.applicationDataSource = applicationDataSource; 210 } 211 212 /** 213 * Indicates whether the legacy KNS module should be included which will include 214 * the KNS spring beans file 215 * 216 * @return boolean true if kns should be supported, false if not 217 */ 218 public boolean isIncludeKnsSpringBeans() { 219 return includeKnsSpringBeans; 220 } 221 222 /** 223 * Setter for the include kns support indicator 224 * 225 * @param includeKnsSpringBeans 226 */ 227 public void setIncludeKnsSpringBeans(boolean includeKnsSpringBeans) { 228 this.includeKnsSpringBeans = includeKnsSpringBeans; 229 } 230}