View Javadoc

1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.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/ecl2.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.krad.config;
17  
18  import org.kuali.rice.core.api.config.module.RunMode;
19  import org.kuali.rice.core.api.config.property.ConfigContext;
20  import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
21  import org.kuali.rice.core.framework.config.module.ModuleConfigurer;
22  import org.kuali.rice.krad.service.DataDictionaryService;
23  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
24  import org.kuali.rice.krad.util.KRADConstants;
25  import org.springframework.context.ApplicationEvent;
26  import org.springframework.context.ApplicationListener;
27  import org.springframework.context.event.ContextRefreshedEvent;
28  import org.springframework.context.event.SmartApplicationListener;
29  
30  import javax.sql.DataSource;
31  import java.util.ArrayList;
32  import java.util.Arrays;
33  import java.util.List;
34  import java.util.concurrent.Executors;
35  import java.util.concurrent.ScheduledExecutorService;
36  import java.util.concurrent.TimeUnit;
37  
38  /**
39   * Rice module configurer for KRAD
40   *
41   * @author Kuali Rice Team (rice.collab@kuali.org)
42   */
43  public class KRADConfigurer extends ModuleConfigurer implements SmartApplicationListener {
44  
45      private DataSource applicationDataSource;
46  
47      private boolean includeKnsSpringBeans;
48  
49      private static final String KRAD_SPRING_BEANS_PATH = "classpath:org/kuali/rice/krad/config/KRADSpringBeans.xml";
50      private static final String KNS_SPRING_BEANS_PATH = "classpath:org/kuali/rice/kns/config/KNSSpringBeans.xml";
51  
52      public KRADConfigurer() {
53          // TODO really the constant value should be "krad" but there's some work to do in order to make
54          // that really work, see KULRICE-6532
55          super(KRADConstants.KR_MODULE_NAME);
56          setValidRunModes(Arrays.asList(RunMode.LOCAL));
57          setIncludeKnsSpringBeans(true);
58      }
59  
60      @Override
61      public void addAdditonalToConfig() {
62          configureDataSource();
63      }
64  
65      @Override
66      public List<String> getPrimarySpringFiles() {
67          final List<String> springFileLocations = new ArrayList<String>();
68          springFileLocations.add(KRAD_SPRING_BEANS_PATH);
69  
70          if (isIncludeKnsSpringBeans()) {
71              springFileLocations.add(KNS_SPRING_BEANS_PATH);
72          }
73  
74          return springFileLocations;
75      }
76  
77      @Override
78      public void onApplicationEvent(ApplicationEvent applicationEvent) {
79          if (applicationEvent instanceof ContextRefreshedEvent) {
80              loadDataDictionary();
81              publishDataDictionaryComponents();
82          }
83      }
84  
85      @Override
86      public boolean supportsEventType(Class<? extends ApplicationEvent> aClass) {
87          return true;
88      }
89  
90      @Override
91      public boolean supportsSourceType(Class<?> aClass) {
92          return true;
93      }
94  
95      @Override
96      public int getOrder() {
97          // return a lower value which will give the data dictionary indexing higher precedence since DD indexing should
98          // be started as soon as it can be
99          return -1000;
100     }
101 
102     /**
103      * Used to "poke" the Data Dictionary again after the Spring Context is initialized.  This is to
104      * allow for modules loaded with KualiModule after the KNS has already been initialized to work.
105      *
106      * Also initializes the DateTimeService
107      */
108     protected void loadDataDictionary() {
109         if (isLoadDataDictionary()) {
110             LOG.info("KRAD Configurer - Loading DD");
111             DataDictionaryService dds = KRADServiceLocatorWeb.getDataDictionaryService();
112             if (dds == null) {
113                 dds = (DataDictionaryService) GlobalResourceLoader
114                         .getService(KRADServiceLocatorWeb.DATA_DICTIONARY_SERVICE);
115             }
116             dds.getDataDictionary().parseDataDictionaryConfigurationFiles(false);
117 
118             if (isValidateDataDictionary()) {
119                 LOG.info("KRAD Configurer - Validating DD");
120                 dds.getDataDictionary().validateDD(isValidateDataDictionaryEboReferences());
121             }
122 
123             // KULRICE-4513 After the Data Dictionary is loaded and validated, perform Data Dictionary bean overrides.
124             dds.getDataDictionary().performBeanOverrides();
125         }
126     }
127 
128     protected void publishDataDictionaryComponents() {
129         if (isComponentPublishingEnabled()) {
130             long delay = getComponentPublishingDelay();
131             LOG.info("Publishing of Data Dictionary components is enabled, scheduling publish after " + delay + " millisecond delay");
132             ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
133             try {
134                 scheduler.schedule(new Runnable() {
135                     @Override
136                     public void run() {
137                         long start = System.currentTimeMillis();
138                         LOG.info("Executing scheduled Data Dictionary component publishing...");
139                         try {
140                             KRADServiceLocatorWeb.getDataDictionaryComponentPublisherService().publishAllComponents();
141                         } catch (RuntimeException e) {
142                             LOG.error("Failed to publish data dictionary components.", e);
143                             throw e;
144                         } finally {
145                             long end = System.currentTimeMillis();
146                             LOG.info("... finished scheduled execution of Data Dictionary component publishing.  Took " + (end-start) + " milliseconds");
147                         }
148                     }
149                 }, delay, TimeUnit.MILLISECONDS);
150             } finally {
151                 scheduler.shutdown();
152             }
153         }
154     }
155 
156     @Override
157     public boolean hasWebInterface() {
158         return true;
159     }
160 
161     /**
162      * Returns true - KNS UI should always be included.
163      *
164      * @see org.kuali.rice.core.framework.config.module.ModuleConfigurer#shouldRenderWebInterface()
165      */
166     @Override
167     public boolean shouldRenderWebInterface() {
168         return true;
169     }
170 
171 
172 
173     public boolean isLoadDataDictionary() {
174         return ConfigContext.getCurrentContextConfig().getBooleanProperty("load.data.dictionary", true);
175     }
176 
177     public boolean isValidateDataDictionary() {
178         return ConfigContext.getCurrentContextConfig().getBooleanProperty("validate.data.dictionary", false);
179     }
180 
181     public boolean isValidateDataDictionaryEboReferences() {
182         return ConfigContext.getCurrentContextConfig().getBooleanProperty("validate.data.dictionary.ebo.references",
183                 false);
184     }
185 
186     public boolean isComponentPublishingEnabled() {
187         return ConfigContext.getCurrentContextConfig().getBooleanProperty(
188                 KRADConstants.Config.COMPONENT_PUBLISHING_ENABLED, false);
189     }
190 
191     public long getComponentPublishingDelay() {
192         return ConfigContext.getCurrentContextConfig().getNumericProperty(KRADConstants.Config.COMPONENT_PUBLISHING_DELAY, 0);
193     }
194 
195     /**
196      * Used to "poke" the Data Dictionary again after the Spring Context is initialized.  This is to
197      * allow for modules loaded with KualiModule after the KNS has already been initialized to work.
198      *
199      * Also initializes the DateTimeService
200      */
201     protected void configureDataSource() {
202         if (getApplicationDataSource() != null) {
203             ConfigContext.getCurrentContextConfig()
204                     .putObject(KRADConstants.KRAD_APPLICATION_DATASOURCE, getApplicationDataSource());
205         }
206     }
207 
208     public DataSource getApplicationDataSource() {
209         return this.applicationDataSource;
210     }
211 
212     public void setApplicationDataSource(DataSource applicationDataSource) {
213         this.applicationDataSource = applicationDataSource;
214     }
215 
216     /**
217      * Indicates whether the legacy KNS module should be included which will include
218      * the KNS spring beans file
219      *
220      * @return boolean true if kns should be supported, false if not
221      */
222     public boolean isIncludeKnsSpringBeans() {
223         return includeKnsSpringBeans;
224     }
225 
226     /**
227      * Setter for the include kns support indicator
228      *
229      * @param includeKnsSpringBeans
230      */
231     public void setIncludeKnsSpringBeans(boolean includeKnsSpringBeans) {
232         this.includeKnsSpringBeans = includeKnsSpringBeans;
233     }
234 }