added create timestamp to database metadata
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / application / CdmApplicationController.java
1 // $Id$
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10
11
12 package eu.etaxonomy.cdm.api.application;
13
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.UUID;
17
18 import org.apache.log4j.Logger;
19 import org.hibernate.SessionFactory;
20 import org.springframework.beans.MutablePropertyValues;
21 import org.springframework.beans.factory.config.BeanDefinition;
22 import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
23 import org.springframework.context.support.AbstractApplicationContext;
24 import org.springframework.context.support.GenericApplicationContext;
25 import org.springframework.core.io.ClassPathResource;
26 import org.springframework.core.io.Resource;
27 import org.springframework.security.providers.ProviderManager;
28 import org.springframework.transaction.PlatformTransactionManager;
29 import org.springframework.transaction.TransactionDefinition;
30 import org.springframework.transaction.TransactionStatus;
31 import org.springframework.transaction.support.DefaultTransactionDefinition;
32
33 import eu.etaxonomy.cdm.api.application.eclipse.EclipseRcpSaveGenericApplicationContext;
34 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
35 import eu.etaxonomy.cdm.api.service.IAgentService;
36 import eu.etaxonomy.cdm.api.service.ICollectionService;
37 import eu.etaxonomy.cdm.api.service.ICommonService;
38 import eu.etaxonomy.cdm.api.service.IDatabaseService;
39 import eu.etaxonomy.cdm.api.service.IDescriptionService;
40 import eu.etaxonomy.cdm.api.service.IFeatureTreeService;
41 import eu.etaxonomy.cdm.api.service.ILocationService;
42 import eu.etaxonomy.cdm.api.service.IMediaService;
43 import eu.etaxonomy.cdm.api.service.INameService;
44 import eu.etaxonomy.cdm.api.service.IOccurrenceService;
45 import eu.etaxonomy.cdm.api.service.IReferenceService;
46 import eu.etaxonomy.cdm.api.service.IService;
47 import eu.etaxonomy.cdm.api.service.ITaxonService;
48 import eu.etaxonomy.cdm.api.service.ITaxonTreeService;
49 import eu.etaxonomy.cdm.api.service.ITermService;
50 import eu.etaxonomy.cdm.api.service.IUserService;
51 import eu.etaxonomy.cdm.api.service.IVocabularyService;
52 import eu.etaxonomy.cdm.database.CdmPersistentDataSource;
53 import eu.etaxonomy.cdm.database.DataSourceNotFoundException;
54 import eu.etaxonomy.cdm.database.DbSchemaValidation;
55 import eu.etaxonomy.cdm.database.ICdmDataSource;
56 import eu.etaxonomy.cdm.model.common.CdmBase;
57 import eu.etaxonomy.cdm.model.common.CdmMetaData;
58 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
59 import eu.etaxonomy.cdm.model.common.TermVocabulary;
60 import eu.etaxonomy.cdm.model.common.User;
61 import eu.etaxonomy.cdm.model.common.VocabularyEnum;
62 import eu.etaxonomy.cdm.model.common.init.TermNotFoundException;
63 import eu.etaxonomy.cdm.model.description.Feature;
64 import eu.etaxonomy.cdm.model.description.FeatureTree;
65
66
67 /**
68 * @author a.mueller
69 *
70 */
71 public class CdmApplicationController {
72 private static final Logger logger = Logger.getLogger(CdmApplicationController.class);
73
74 public static final String DEFAULT_APPLICATION_CONTEXT_RESOURCE = "/eu/etaxonomy/cdm/defaultApplicationContext.xml";
75
76 public AbstractApplicationContext applicationContext;
77 private ICdmApplicationConfiguration configuration;
78 private Resource applicationContextResource;
79
80 final static DbSchemaValidation defaultDbSchemaValidation = DbSchemaValidation.VALIDATE;
81
82
83
84 /**
85 * Constructor, opens an spring 2.5 ApplicationContext by using the default data source
86 */
87 public static CdmApplicationController NewInstance() throws DataSourceNotFoundException, TermNotFoundException {
88 logger.info("Start CdmApplicationController with default data source");
89 CdmPersistentDataSource dataSource = CdmPersistentDataSource.NewDefaultInstance();
90 DbSchemaValidation dbSchemaValidation = defaultDbSchemaValidation;
91 return new CdmApplicationController(null, dataSource, dbSchemaValidation, false);
92 }
93
94
95
96 /**
97 * Constructor, opens an spring 2.5 ApplicationContext by using the default data source
98 * @param dbSchemaValidation validation type for database schema
99 */
100 public static CdmApplicationController NewInstance(DbSchemaValidation dbSchemaValidation) throws DataSourceNotFoundException, TermNotFoundException {
101 logger.info("Start CdmApplicationController with default data source");
102 CdmPersistentDataSource dataSource = CdmPersistentDataSource.NewDefaultInstance();
103 if (dbSchemaValidation == null){
104 dbSchemaValidation = defaultDbSchemaValidation;
105 }
106 return new CdmApplicationController(null, dataSource, dbSchemaValidation, false);
107 }
108
109
110 /**
111 * Constructor, opens an spring 2.5 ApplicationContext by using the according data source and the
112 * default database schema validation type
113 * @param dataSource
114 */
115 public static CdmApplicationController NewInstance(ICdmDataSource dataSource)
116 throws DataSourceNotFoundException, TermNotFoundException{
117 return new CdmApplicationController(null, dataSource, defaultDbSchemaValidation, false);
118 }
119
120 public static CdmApplicationController NewInstance(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation)
121 throws DataSourceNotFoundException, TermNotFoundException{
122 return new CdmApplicationController(null, dataSource, dbSchemaValidation, false);
123 }
124
125 public static CdmApplicationController NewInstance(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading)
126 throws DataSourceNotFoundException, TermNotFoundException{
127 return new CdmApplicationController(null, dataSource, dbSchemaValidation, omitTermLoading);
128 }
129
130 public static CdmApplicationController NewInstance(Resource applicationContextResource, ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading)
131 throws DataSourceNotFoundException, TermNotFoundException{
132 return new CdmApplicationController(applicationContextResource, dataSource, dbSchemaValidation, omitTermLoading);
133 }
134
135 /**
136 * Constructor, opens an spring 2.5 ApplicationContext by using the according data source
137 * @param dataSource
138 * @param dbSchemaValidation
139 * @param omitTermLoading
140 */
141 private CdmApplicationController(Resource applicationContextResource, ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading){
142 logger.info("Start CdmApplicationController with datasource: " + dataSource.getName());
143 if (applicationContextResource != null){
144 this.applicationContextResource = applicationContextResource;
145 }else{
146 this.applicationContextResource = new ClassPathResource(DEFAULT_APPLICATION_CONTEXT_RESOURCE);
147 }
148
149 setNewDataSource(dataSource, dbSchemaValidation, omitTermLoading);
150
151 // if (setNewDataSource(dataSource, dbSchemaValidation, omitTermLoading) == false){
152 // throw new DataSourceNotFoundException("Wrong datasource: " + dataSource );
153 // }
154 }
155
156
157 /**
158 * Sets the application context to a new spring ApplicationContext by using the according data source and initializes the Controller.
159 * @param dataSource
160 */
161 private boolean setNewDataSource(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading){
162 if (dbSchemaValidation == null){
163 dbSchemaValidation = defaultDbSchemaValidation;
164 }
165 logger.info("Connecting to '" + dataSource.getName() + "'");
166
167
168 GenericApplicationContext appContext;
169 // try {
170 appContext = new EclipseRcpSaveGenericApplicationContext();
171
172 BeanDefinition datasourceBean = dataSource.getDatasourceBean();
173 datasourceBean.setAttribute("isLazy", false);
174 appContext.registerBeanDefinition("dataSource", datasourceBean);
175
176 BeanDefinition hibernatePropBean= dataSource.getHibernatePropertiesBean(dbSchemaValidation);
177 appContext.registerBeanDefinition("hibernateProperties", hibernatePropBean);
178
179 XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(appContext);
180 xmlReader.loadBeanDefinitions(this.applicationContextResource);
181
182 //omitTerms
183 String initializerName = "persistentTermInitializer";
184 BeanDefinition beanDef = appContext.getBeanDefinition(initializerName);
185 MutablePropertyValues values = beanDef.getPropertyValues();
186 values.addPropertyValue("omit", omitTermLoading);
187
188 appContext.refresh();
189 appContext.start();
190
191 setApplicationContext(appContext);
192
193 //initialize user and metaData for new databases
194 int userCount = getUserService().count(User.class);
195 if (userCount == 0 ){
196 createAdminUser();
197 }
198 int metaDataCount = getCommonService().getCdmMetaData().size();
199 if (metaDataCount == 0){
200 createMetadata();
201 }
202
203 return true;
204 }
205
206 private void createAdminUser(){
207 User firstUser = User.NewInstance("admin", "0000");
208 getUserService().save(firstUser);
209 logger.info("Admin user created.");
210 }
211
212 private void createMetadata(){
213 List<CdmMetaData> metaData = CdmMetaData.defaultMetaData();
214 getCommonService().saveAllMetaData(metaData);
215 logger.info("Metadata created.");
216 }
217
218
219 /**
220 * Tests if some DefinedTermsAreMissing.
221 * @return true, if at least one is missing, else false
222 */
223 public boolean testDefinedTermsAreMissing(){
224 UUID englishUuid = UUID.fromString("e9f8cdb7-6819-44e8-95d3-e2d0690c3523");
225 DefinedTermBase<?> english = this.getTermService().getByUri(englishUuid.toString());
226 if ( english == null || ! english.getUuid().equals(englishUuid)){
227 return true;
228 }else{
229 return false;
230 }
231 }
232
233
234 /**
235 * Changes the ApplicationContext to the new dataSource
236 * @param dataSource
237 */
238 public boolean changeDataSource(ICdmDataSource dataSource){
239 //logger.info("Change datasource to : " + dataSource);
240 return setNewDataSource(dataSource, DbSchemaValidation.VALIDATE, false);
241 }
242
243 /**
244 * Changes the ApplicationContext to the new dataSource
245 * @param dataSource
246 * @param dbSchemaValidation
247 */
248 public boolean changeDataSource(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation){
249 //logger.info("Change datasource to : " + dataSource);
250 return setNewDataSource(dataSource, dbSchemaValidation, false);
251 }
252
253 /**
254 * Changes the ApplicationContext to the new dataSource
255 * @param dataSource
256 * @param dbSchemaValidation
257 * @param omitTermLoading
258 */
259 public boolean changeDataSource(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading){
260 logger.info("Change datasource to : " + dataSource);
261 return setNewDataSource(dataSource, dbSchemaValidation, omitTermLoading);
262 }
263
264 /**
265 * Sets a new application Context.
266 * @param ac
267 */
268 public void setApplicationContext(AbstractApplicationContext ac){
269 closeApplicationContext(); //closes old application context if necessary
270 applicationContext = ac;
271 applicationContext.registerShutdownHook();
272 init();
273 }
274
275 /* (non-Javadoc)
276 * @see java.lang.Object#finalize()
277 */
278 public void finalize(){
279 close();
280 }
281
282 /**
283 * closes the application
284 */
285 public void close(){
286 closeApplicationContext();
287 }
288
289 /**
290 * closes the application context
291 */
292 private void closeApplicationContext(){
293 if (applicationContext != null){
294 logger.info("Close ApplicationContext");
295 applicationContext.close();
296 }
297 }
298
299 private void init(){
300 logger.debug("Init " + this.getClass().getName() + " ... ");
301 if (logger.isDebugEnabled()){for (String beanName : applicationContext.getBeanDefinitionNames()){ logger.debug(beanName);}}
302 //TODO delete next row (was just for testing)
303 if (logger.isInfoEnabled()){
304 logger.info("Registered Beans: ");
305 String[] beans = applicationContext.getBeanDefinitionNames();
306 for (String bean:beans){
307 logger.info(bean);
308 }
309 }
310 configuration = (ICdmApplicationConfiguration)applicationContext.getBean("cdmApplicationDefaultConfiguration");
311 getDatabaseService().setApplicationController(this);
312 }
313
314
315
316 /* ****** Services *********/
317 public final INameService getNameService(){
318 return configuration.getNameService();
319 }
320
321 public final ITaxonService getTaxonService(){
322 return configuration.getTaxonService();
323 }
324
325 public final ITaxonTreeService getTaxonTreeService(){
326 return configuration.getTaxonTreeService();
327 }
328
329 public final IReferenceService getReferenceService(){
330 return configuration.getReferenceService();
331 }
332
333 public final IAgentService getAgentService(){
334 return configuration.getAgentService();
335 }
336
337 public final IDatabaseService getDatabaseService(){
338 return configuration.getDatabaseService();
339 }
340
341 public final ITermService getTermService(){
342 return configuration.getTermService();
343 }
344
345 public final IDescriptionService getDescriptionService(){
346 return configuration.getDescriptionService();
347 }
348
349 public final IOccurrenceService getOccurrenceService(){
350 return configuration.getOccurrenceService();
351 }
352
353 public final IMediaService getMediaService(){
354 return configuration.getMediaService();
355 }
356
357 public final ICommonService getCommonService(){
358 return configuration.getCommonService();
359 }
360
361 public final ILocationService getLocationService(){
362 return configuration.getLocationService();
363 }
364
365 public final IUserService getUserService(){
366 return configuration.getUserService();
367 }
368
369 public final ICollectionService getCollectionService(){
370 return configuration.getCollectionService();
371 }
372
373 public final IFeatureTreeService getFeatureTreeService(){
374 return configuration.getFeatureTreeService();
375 }
376
377 public final IVocabularyService getVocabularyService(){
378 return configuration.getVocabularyService();
379 }
380
381 public final IService<CdmBase> getMainService(){
382 return configuration.getMainService();
383 }
384
385 public final ConversationHolder NewConversation(){
386 //return (ConversationHolder)applicationContext.getBean("conversationHolder");
387 return configuration.NewConversation();
388 }
389
390
391 public final ProviderManager getAuthenticationManager(){
392 return configuration.getAuthenticationManager();
393 }
394
395 public final Object getBean(String name){
396 return this.applicationContext.getBean(name);
397 }
398
399 /*
400 * OLD TRANSACTION STUFF
401 */
402
403 /* **** flush ***********/
404 public void flush() {
405 SessionFactory sf = (SessionFactory)applicationContext.getBean("sessionFactory");
406 sf.getCurrentSession().flush();
407 }
408
409 public SessionFactory getSessionFactory(){
410 return (SessionFactory)applicationContext.getBean("sessionFactory");
411 }
412
413 public TransactionStatus startTransaction() {
414
415 return startTransaction(false);
416 }
417
418 public TransactionStatus startTransaction(Boolean readOnly) {
419
420 PlatformTransactionManager txManager = configuration.getTransactionManager();
421
422 DefaultTransactionDefinition defaultTxDef = new DefaultTransactionDefinition();
423 defaultTxDef.setReadOnly(readOnly);
424 TransactionDefinition txDef = defaultTxDef;
425
426 // Log some transaction-related debug information.
427 if (logger.isDebugEnabled()) {
428 logger.debug("Transaction name = " + txDef.getName());
429 logger.debug("Transaction facets:");
430 logger.debug("Propagation behavior = " + txDef.getPropagationBehavior());
431 logger.debug("Isolation level = " + txDef.getIsolationLevel());
432 logger.debug("Timeout = " + txDef.getTimeout());
433 logger.debug("Read Only = " + txDef.isReadOnly());
434 // org.springframework.orm.hibernate3.HibernateTransactionManager
435 // provides more transaction/session-related debug information.
436 }
437
438 TransactionStatus txStatus = txManager.getTransaction(txDef);
439 return txStatus;
440 }
441
442 public void commitTransaction(TransactionStatus txStatus){
443 PlatformTransactionManager txManager = configuration.getTransactionManager();
444 txManager.commit(txStatus);
445 return;
446 }
447
448 }