(no commit message)
[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.EnumSet;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Set;
18 import java.util.UUID;
19
20 import org.apache.log4j.Logger;
21 import org.hibernate.SessionFactory;
22 import org.springframework.beans.MutablePropertyValues;
23 import org.springframework.beans.factory.config.BeanDefinition;
24 import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
25 import org.springframework.context.ApplicationListener;
26 import org.springframework.context.support.AbstractApplicationContext;
27 import org.springframework.core.io.ClassPathResource;
28 import org.springframework.core.io.Resource;
29 import org.springframework.security.access.PermissionEvaluator;
30 import org.springframework.security.authentication.ProviderManager;
31 import org.springframework.security.core.GrantedAuthority;
32 import org.springframework.security.core.context.SecurityContext;
33 import org.springframework.security.core.context.SecurityContextHolder;
34 import org.springframework.transaction.PlatformTransactionManager;
35 import org.springframework.transaction.TransactionStatus;
36
37 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
38 import eu.etaxonomy.cdm.api.service.IAgentService;
39 import eu.etaxonomy.cdm.api.service.IClassificationService;
40 import eu.etaxonomy.cdm.api.service.ICollectionService;
41 import eu.etaxonomy.cdm.api.service.ICommonService;
42 import eu.etaxonomy.cdm.api.service.IDatabaseService;
43 import eu.etaxonomy.cdm.api.service.IDescriptionService;
44 import eu.etaxonomy.cdm.api.service.IFeatureNodeService;
45 import eu.etaxonomy.cdm.api.service.IFeatureTreeService;
46 import eu.etaxonomy.cdm.api.service.IGrantedAuthorityService;
47 import eu.etaxonomy.cdm.api.service.IGroupService;
48 import eu.etaxonomy.cdm.api.service.IIdentificationKeyService;
49 import eu.etaxonomy.cdm.api.service.ILocationService;
50 import eu.etaxonomy.cdm.api.service.IMediaService;
51 import eu.etaxonomy.cdm.api.service.INameService;
52 import eu.etaxonomy.cdm.api.service.IOccurrenceService;
53 import eu.etaxonomy.cdm.api.service.IPolytomousKeyNodeService;
54 import eu.etaxonomy.cdm.api.service.IPolytomousKeyService;
55 import eu.etaxonomy.cdm.api.service.IReferenceService;
56 import eu.etaxonomy.cdm.api.service.IService;
57 import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
58 import eu.etaxonomy.cdm.api.service.ITaxonService;
59 import eu.etaxonomy.cdm.api.service.ITermService;
60 import eu.etaxonomy.cdm.api.service.IUserService;
61 import eu.etaxonomy.cdm.api.service.IVocabularyService;
62 import eu.etaxonomy.cdm.api.service.IWorkingSetService;
63 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
64 import eu.etaxonomy.cdm.common.monitor.NullProgressMonitor;
65 import eu.etaxonomy.cdm.common.monitor.SubProgressMonitor;
66 import eu.etaxonomy.cdm.database.CdmPersistentDataSource;
67 import eu.etaxonomy.cdm.database.DataSourceNotFoundException;
68 import eu.etaxonomy.cdm.database.DbSchemaValidation;
69 import eu.etaxonomy.cdm.database.ICdmDataSource;
70 import eu.etaxonomy.cdm.model.common.CdmBase;
71 import eu.etaxonomy.cdm.model.common.CdmMetaData;
72 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
73 import eu.etaxonomy.cdm.model.common.GrantedAuthorityImpl;
74 import eu.etaxonomy.cdm.model.common.User;
75 import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
76 import eu.etaxonomy.cdm.persistence.hibernate.permission.Operation;
77 import eu.etaxonomy.cdm.persistence.hibernate.permission.Role;
78
79
80 /**
81 * @author a.mueller
82 *
83 */
84 public class CdmApplicationController implements ICdmApplicationConfiguration{
85 private static final Logger logger = Logger.getLogger(CdmApplicationController.class);
86
87 public static final String DEFAULT_APPLICATION_CONTEXT_RESOURCE = "/eu/etaxonomy/cdm/defaultApplicationContext.xml";
88
89 public AbstractApplicationContext applicationContext;
90 private ICdmApplicationConfiguration configuration;
91 private Resource applicationContextResource;
92
93 private IProgressMonitor progressMonitor;
94
95 final protected static DbSchemaValidation defaultDbSchemaValidation = DbSchemaValidation.VALIDATE;
96
97
98
99 /**
100 * Constructor, opens a spring ApplicationContext by using the default data source
101 * @throws DataSourceNotFoundException
102 */
103 public static CdmApplicationController NewInstance() throws DataSourceNotFoundException {
104 logger.info("Start CdmApplicationController with default data source");
105 CdmPersistentDataSource dataSource = getDefaultDatasource();
106 DbSchemaValidation dbSchemaValidation = defaultDbSchemaValidation;
107 return CdmApplicationController.NewInstance(null, dataSource, dbSchemaValidation, false);
108 }
109
110 /**
111 * Constructor, opens a spring ApplicationContext by using the default data source
112 * @param dbSchemaValidation validation type for database schema
113 * @throws DataSourceNotFoundException
114 */
115 public static CdmApplicationController NewInstance(DbSchemaValidation dbSchemaValidation) throws DataSourceNotFoundException {
116 logger.info("Start CdmApplicationController with default data source");
117 CdmPersistentDataSource dataSource = getDefaultDatasource();
118 return CdmApplicationController.NewInstance(null, dataSource, dbSchemaValidation, false);
119 }
120
121
122 /**
123 * Constructor, opens an spring ApplicationContext by using the according data source and the
124 * default database schema validation type
125 * @param dataSource
126 */
127 public static CdmApplicationController NewInstance(ICdmDataSource dataSource) {
128 return CdmApplicationController.NewInstance(null, dataSource, defaultDbSchemaValidation, false);
129 }
130
131 public static CdmApplicationController NewInstance(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation) {
132 return CdmApplicationController.NewInstance(null, dataSource, dbSchemaValidation, false);
133 }
134
135 public static CdmApplicationController NewInstance(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading) {
136 return CdmApplicationController.NewInstance(null, dataSource, dbSchemaValidation, omitTermLoading);
137 }
138
139 public static CdmApplicationController NewInstance(Resource applicationContextResource, ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading) {
140 return CdmApplicationController.NewInstance(applicationContextResource, dataSource, dbSchemaValidation, omitTermLoading, null);
141 }
142
143 public static CdmApplicationController NewInstance(Resource applicationContextResource, ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading, IProgressMonitor progressMonitor) {
144 return new CdmApplicationController(applicationContextResource, dataSource, dbSchemaValidation, omitTermLoading, progressMonitor, null);
145 }
146
147 //TODO discuss need for listeners before commit to trunk
148 // public static CdmApplicationController NewInstance(Resource applicationContextResource, ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading, IProgressMonitor progressMonitor, List<ApplicationListener> listeners) {
149 // return new CdmApplicationController(applicationContextResource, dataSource, dbSchemaValidation, omitTermLoading, progressMonitor,listeners);
150 // }
151
152
153 /**
154 * @return
155 */
156 protected static ClassPathResource getClasspathResource() {
157 return new ClassPathResource(DEFAULT_APPLICATION_CONTEXT_RESOURCE);
158 }
159
160 /**
161 * @return
162 * @throws DataSourceNotFoundException
163 */
164 protected static CdmPersistentDataSource getDefaultDatasource() throws DataSourceNotFoundException {
165 CdmPersistentDataSource dataSource = CdmPersistentDataSource.NewDefaultInstance();
166 return dataSource;
167 }
168
169
170 /**
171 * Constructor, opens an spring 2.5 ApplicationContext by using the according data source
172 * @param dataSource
173 * @param dbSchemaValidation
174 * @param omitTermLoading
175 */
176 protected CdmApplicationController(Resource applicationContextResource, ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading, IProgressMonitor progressMonitor, List<ApplicationListener> listeners){
177 logger.info("Start CdmApplicationController with datasource: " + dataSource.getName());
178
179 if (dbSchemaValidation == null){
180 dbSchemaValidation = defaultDbSchemaValidation;
181 }
182 this.applicationContextResource = applicationContextResource != null ? applicationContextResource : getClasspathResource();
183 this.progressMonitor = progressMonitor != null ? progressMonitor : new NullProgressMonitor();
184
185 setNewDataSource(dataSource, dbSchemaValidation, omitTermLoading, listeners);
186 }
187
188
189 /**
190 * Sets the application context to a new spring ApplicationContext by using the according data source and initializes the Controller.
191 * @param dataSource
192 */
193 private boolean setNewDataSource(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading, List<ApplicationListener> listeners){
194
195 if (dbSchemaValidation == null){
196 dbSchemaValidation = defaultDbSchemaValidation;
197 }
198 logger.info("Connecting to '" + dataSource.getName() + "'");
199
200 MonitoredGenericApplicationContext applicationContext = new MonitoredGenericApplicationContext();
201 int refreshTasks = 45;
202 int nTasks = 5 + refreshTasks;
203 // nTasks += applicationContext.countTasks();
204 progressMonitor.beginTask("Connecting to '" + dataSource.getName() + "'", nTasks);
205
206 // progressMonitor.worked(1);
207
208 BeanDefinition datasourceBean = dataSource.getDatasourceBean();
209 datasourceBean.setAttribute("isLazy", false);
210 progressMonitor.subTask("Registering datasource.");
211 applicationContext.registerBeanDefinition("dataSource", datasourceBean);
212 progressMonitor.worked(1);
213
214 BeanDefinition hibernatePropBean= dataSource.getHibernatePropertiesBean(dbSchemaValidation);
215 applicationContext.registerBeanDefinition("hibernateProperties", hibernatePropBean);
216
217 XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(applicationContext);
218 progressMonitor.subTask("Registering resources.");
219 xmlReader.loadBeanDefinitions(applicationContextResource);
220 progressMonitor.worked(1);
221
222 //omitTerms
223 if (omitTermLoading == true){
224 String initializerName = "persistentTermInitializer";
225 BeanDefinition beanDef = applicationContext.getBeanDefinition(initializerName);
226 MutablePropertyValues values = beanDef.getPropertyValues();
227 values.addPropertyValue("omit", omitTermLoading);
228 }
229
230 if (listeners != null){
231 for(ApplicationListener listener : listeners){
232 applicationContext.addApplicationListener(listener);
233 }
234 }
235
236 // String message = "Start application context. This might take a while ...";
237 //// progressMonitor.subTask(message);
238 // SubProgressMonitor subMonitor= new SubProgressMonitor(progressMonitor, 10);
239 // subMonitor.beginTask(message, 2);
240 // applicationContext.setProgressMonitor(subMonitor);
241
242 applicationContext.refresh(new SubProgressMonitor(progressMonitor, refreshTasks));
243 applicationContext.start();
244 // progressMonitor.worked(1);
245
246 progressMonitor.subTask("Cleaning up.");
247 setApplicationContext(applicationContext);
248 progressMonitor.worked(1);
249
250 progressMonitor.done();
251 return true;
252 }
253
254
255
256
257
258 /**
259 * Tests if some DefinedTermsAreMissing.
260 * @return true, if at least one is missing, else false
261 */
262 public boolean testDefinedTermsAreMissing(){
263 UUID englishUuid = UUID.fromString("e9f8cdb7-6819-44e8-95d3-e2d0690c3523");
264 DefinedTermBase<?> english = this.getTermService().load(englishUuid);
265 if ( english == null || ! english.getUuid().equals(englishUuid)){
266 return true;
267 }else{
268 return false;
269 }
270 }
271
272
273 /**
274 * Changes the ApplicationContext to the new dataSource
275 * @param dataSource
276 */
277 public boolean changeDataSource(ICdmDataSource dataSource){
278 //logger.info("Change datasource to : " + dataSource);
279 return setNewDataSource(dataSource, DbSchemaValidation.VALIDATE, false, null);
280 }
281
282 /**
283 * Changes the ApplicationContext to the new dataSource
284 * @param dataSource
285 * @param dbSchemaValidation
286 */
287 public boolean changeDataSource(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation){
288 //logger.info("Change datasource to : " + dataSource);
289 return setNewDataSource(dataSource, dbSchemaValidation, false, null);
290 }
291
292 /**
293 * Changes the ApplicationContext to the new dataSource
294 * @param dataSource
295 * @param dbSchemaValidation
296 * @param omitTermLoading
297 */
298 public boolean changeDataSource(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading){
299 logger.info("Change datasource to : " + dataSource);
300 return setNewDataSource(dataSource, dbSchemaValidation, omitTermLoading, null);
301 }
302
303 /**
304 * Changes the ApplicationContext to the new dataSource
305 * @param dataSource
306 * @param dbSchemaValidation
307 * @param omitTermLoading
308 */
309 public boolean changeDataSource(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading, List<ApplicationListener> listeners){
310 logger.info("Change datasource to : " + dataSource);
311 return setNewDataSource(dataSource, dbSchemaValidation, omitTermLoading, listeners);
312 }
313
314 /**
315 * Sets a new application Context.
316 * @param ac
317 */
318 public void setApplicationContext(AbstractApplicationContext ac){
319 closeApplicationContext(); //closes old application context if necessary
320 applicationContext = ac;
321 applicationContext.registerShutdownHook();
322 init();
323 }
324
325 /* (non-Javadoc)
326 * @see java.lang.Object#finalize()
327 */
328 public void finalize(){
329 close();
330 }
331
332 /**
333 * closes the application
334 */
335 public void close(){
336 closeApplicationContext();
337 }
338
339 /**
340 * closes the application context
341 */
342 protected void closeApplicationContext(){
343 if (applicationContext != null){
344 logger.info("Close ApplicationContext");
345 applicationContext.close();
346 }
347 }
348
349 protected void init(){
350 logger.debug("Init " + this.getClass().getName() + " ... ");
351 if (logger.isDebugEnabled()){for (String beanName : applicationContext.getBeanDefinitionNames()){ logger.debug(beanName);}}
352 //TODO delete next row (was just for testing)
353 if (logger.isInfoEnabled()){
354 logger.info("Registered Beans: ");
355 String[] beanNames = applicationContext.getBeanDefinitionNames();
356 for (String beanName : beanNames){
357 logger.info(beanName);
358 }
359 }
360 configuration = (ICdmApplicationConfiguration)applicationContext.getBean("cdmApplicationDefaultConfiguration");
361 getDatabaseService().setApplicationController(this);
362 }
363
364
365
366 /* ****** Services *********/
367 public final INameService getNameService(){
368 return configuration.getNameService();
369 }
370
371 public final ITaxonService getTaxonService(){
372 return configuration.getTaxonService();
373 }
374
375 public final IClassificationService getClassificationService(){
376 return configuration.getClassificationService();
377 }
378
379 public final ITaxonNodeService getTaxonNodeService(){
380 return configuration.getTaxonNodeService();
381 }
382
383 public final IReferenceService getReferenceService(){
384 return configuration.getReferenceService();
385 }
386
387 public final IAgentService getAgentService(){
388 return configuration.getAgentService();
389 }
390
391 public final IDatabaseService getDatabaseService(){
392 return configuration.getDatabaseService();
393 }
394
395 public final ITermService getTermService(){
396 return configuration.getTermService();
397 }
398
399 public final IDescriptionService getDescriptionService(){
400 return configuration.getDescriptionService();
401 }
402
403 public final IOccurrenceService getOccurrenceService(){
404 return configuration.getOccurrenceService();
405 }
406
407 public final IMediaService getMediaService(){
408 return configuration.getMediaService();
409 }
410
411 public final ICommonService getCommonService(){
412 return configuration.getCommonService();
413 }
414
415 public final ILocationService getLocationService(){
416 return configuration.getLocationService();
417 }
418
419 public final IUserService getUserService(){
420 return configuration.getUserService();
421 }
422
423 public final IGrantedAuthorityService getGrantedAuthorityService(){
424 return configuration.getGrantedAuthorityService();
425 }
426
427 public IGroupService getGroupService() {
428 return configuration.getGroupService();
429 }
430
431 public final ICollectionService getCollectionService(){
432 return configuration.getCollectionService();
433 }
434
435 public final IFeatureTreeService getFeatureTreeService(){
436 return configuration.getFeatureTreeService();
437 }
438
439 public final IFeatureNodeService getFeatureNodeService(){
440 return configuration.getFeatureNodeService();
441 }
442
443 public final IVocabularyService getVocabularyService(){
444 return configuration.getVocabularyService();
445 }
446
447 public final IIdentificationKeyService getIdentificationKeyService(){
448 return configuration.getIdentificationKeyService();
449 }
450
451 public final IPolytomousKeyService getPolytomousKeyService(){
452 return configuration.getPolytomousKeyService();
453 }
454
455 public final IPolytomousKeyNodeService getPolytomousKeyNodeService(){
456 return configuration.getPolytomousKeyNodeService();
457 }
458
459 public final IService<CdmBase> getMainService(){
460 return configuration.getMainService();
461 }
462
463 public final IWorkingSetService getWorkingSetService(){
464 return configuration.getWorkingSetService();
465 }
466
467 public final ConversationHolder NewConversation(){
468 //return (ConversationHolder)applicationContext.getBean("conversationHolder");
469 return configuration.NewConversation();
470 }
471
472
473 /* **** Security ***** */
474
475 /* (non-Javadoc)
476 * @see eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration#getAuthenticationManager()
477 */
478 public final ProviderManager getAuthenticationManager(){
479 return configuration.getAuthenticationManager();
480 }
481
482
483 public PermissionEvaluator getPermissionEvaluator() {
484 return configuration.getPermissionEvaluator();
485 }
486
487 /**
488 * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
489 *
490 * @param targetDomainObject
491 * @param permission
492 * @return
493 */
494 public boolean currentAuthentiationHasPermissions(CdmBase targetDomainObject, EnumSet<CRUD> permission){
495 SecurityContext context = SecurityContextHolder.getContext();
496 return getPermissionEvaluator().hasPermission(context.getAuthentication(), targetDomainObject, permission);
497 }
498
499
500 @Override
501 public final PlatformTransactionManager getTransactionManager() {
502 return configuration.getTransactionManager();
503 }
504
505 public final Object getBean(String name){
506 return this.applicationContext.getBean(name);
507 }
508
509 /*
510 * OLD TRANSACTION STUFF
511 */
512
513 /* **** flush ***********/
514 public void flush() {
515 SessionFactory sf = (SessionFactory)applicationContext.getBean("sessionFactory");
516 sf.getCurrentSession().flush();
517 }
518
519 public SessionFactory getSessionFactory(){
520 return (SessionFactory)applicationContext.getBean("sessionFactory");
521 }
522
523 public TransactionStatus startTransaction() {
524 return startTransaction(false);
525 }
526
527 public TransactionStatus startTransaction(Boolean readOnly) {
528 return configuration.startTransaction(readOnly);
529 }
530
531 public void commitTransaction(TransactionStatus txStatus){
532 PlatformTransactionManager txManager = configuration.getTransactionManager();
533 txManager.commit(txStatus);
534 return;
535 }
536
537 }