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