Project

General

Profile

Download (21.9 KB) Statistics
| Branch: | Tag: | Revision:
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

    
78

    
79
/**
80
 * @author a.mueller
81
 *
82
 */
83
public class CdmApplicationController implements ICdmApplicationConfiguration{
84
    private static final Logger logger = Logger.getLogger(CdmApplicationController.class);
85

    
86
    public static final String DEFAULT_APPLICATION_CONTEXT_RESOURCE = "/eu/etaxonomy/cdm/defaultApplicationContext.xml";
87

    
88
    public AbstractApplicationContext applicationContext;
89
    private ICdmApplicationConfiguration configuration;
90
    private Resource applicationContextResource;
91

    
92
    private IProgressMonitor progressMonitor;
93

    
94
    final protected static DbSchemaValidation defaultDbSchemaValidation = DbSchemaValidation.VALIDATE;
95

    
96

    
97

    
98
    /**
99
     * Constructor, opens a spring ApplicationContext by using the default data source
100
     * @throws DataSourceNotFoundException
101
     */
102
    public static CdmApplicationController NewInstance() throws DataSourceNotFoundException {
103
        logger.info("Start CdmApplicationController with default data source");
104
        CdmPersistentDataSource dataSource = getDefaultDatasource();
105
        DbSchemaValidation dbSchemaValidation = defaultDbSchemaValidation;
106
        return CdmApplicationController.NewInstance(null, dataSource, dbSchemaValidation, false);
107
    }
108

    
109
    /**
110
     * Constructor, opens a spring ApplicationContext by using the default data source
111
     * @param dbSchemaValidation validation type for database schema
112
     * @throws DataSourceNotFoundException
113
     */
114
    public static CdmApplicationController NewInstance(DbSchemaValidation dbSchemaValidation) throws DataSourceNotFoundException {
115
        logger.info("Start CdmApplicationController with default data source");
116
        CdmPersistentDataSource dataSource = getDefaultDatasource();
117
        return CdmApplicationController.NewInstance(null, dataSource, dbSchemaValidation, false);
118
    }
119

    
120

    
121
    /**
122
     * Constructor, opens an spring ApplicationContext by using the according data source and the
123
     * default database schema validation type
124
     * @param dataSource
125
     */
126
    public static CdmApplicationController NewInstance(ICdmDataSource dataSource) {
127
        return CdmApplicationController.NewInstance(null, dataSource, defaultDbSchemaValidation, false);
128
    }
129

    
130
    public static CdmApplicationController NewInstance(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation) {
131
        return CdmApplicationController.NewInstance(null, dataSource, dbSchemaValidation, false);
132
    }
133

    
134
    public static CdmApplicationController NewInstance(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading) {
135
        return CdmApplicationController.NewInstance(null, dataSource, dbSchemaValidation, omitTermLoading);
136
    }
137

    
138
    public static CdmApplicationController NewInstance(Resource applicationContextResource, ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading) {
139
        return CdmApplicationController.NewInstance(applicationContextResource, dataSource, dbSchemaValidation, omitTermLoading, null);
140
    }
141

    
142
    public static CdmApplicationController NewInstance(Resource applicationContextResource, ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading, IProgressMonitor progressMonitor) {
143
        return new CdmApplicationController(applicationContextResource, dataSource, dbSchemaValidation, omitTermLoading, progressMonitor, null);
144
    }
145

    
146
    //TODO discuss need for listeners before commit to trunk
147
//	public static CdmApplicationController NewInstance(Resource applicationContextResource, ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading, IProgressMonitor progressMonitor, List<ApplicationListener> listeners) {
148
//		return new CdmApplicationController(applicationContextResource, dataSource, dbSchemaValidation, omitTermLoading, progressMonitor,listeners);
149
//	}
150

    
151

    
152
    /**
153
     * @return
154
     */
155
    protected static ClassPathResource getClasspathResource() {
156
        return new ClassPathResource(DEFAULT_APPLICATION_CONTEXT_RESOURCE);
157
    }
158

    
159
    /**
160
     * @return
161
     * @throws DataSourceNotFoundException
162
     */
163
    protected static CdmPersistentDataSource getDefaultDatasource() throws DataSourceNotFoundException {
164
        CdmPersistentDataSource dataSource = CdmPersistentDataSource.NewDefaultInstance();
165
        return dataSource;
166
    }
167

    
168

    
169
    /**
170
     * Constructor, opens an spring 2.5 ApplicationContext by using the according data source
171
     * @param dataSource
172
     * @param dbSchemaValidation
173
     * @param omitTermLoading
174
     */
175
    protected CdmApplicationController(Resource applicationContextResource, ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading, IProgressMonitor progressMonitor, List<ApplicationListener> listeners){
176
        logger.info("Start CdmApplicationController with datasource: " + dataSource.getName());
177

    
178
        if (dbSchemaValidation == null){
179
            dbSchemaValidation = defaultDbSchemaValidation;
180
        }
181
        this.applicationContextResource = applicationContextResource != null ? applicationContextResource : getClasspathResource();
182
        this.progressMonitor = progressMonitor != null ? progressMonitor : new NullProgressMonitor();
183

    
184
        setNewDataSource(dataSource, dbSchemaValidation, omitTermLoading, listeners);
185
    }
186

    
187

    
188
    /**
189
     * Sets the application context to a new spring ApplicationContext by using the according data source and initializes the Controller.
190
     * @param dataSource
191
     */
192
    private boolean setNewDataSource(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading, List<ApplicationListener> listeners){
193

    
194
        if (dbSchemaValidation == null){
195
            dbSchemaValidation = defaultDbSchemaValidation;
196
        }
197
        logger.info("Connecting to '" + dataSource.getName() + "'");
198

    
199
        MonitoredGenericApplicationContext applicationContext =  new MonitoredGenericApplicationContext();
200
        int refreshTasks = 45;
201
        int nTasks = 5 + refreshTasks;
202
//		nTasks += applicationContext.countTasks();
203
        progressMonitor.beginTask("Connecting to '" + dataSource.getName() + "'", nTasks);
204

    
205
//		progressMonitor.worked(1);
206

    
207
        BeanDefinition datasourceBean = dataSource.getDatasourceBean();
208
        datasourceBean.setAttribute("isLazy", false);
209
        progressMonitor.subTask("Registering datasource.");
210
        applicationContext.registerBeanDefinition("dataSource", datasourceBean);
211
        progressMonitor.worked(1);
212

    
213
        BeanDefinition hibernatePropBean= dataSource.getHibernatePropertiesBean(dbSchemaValidation);
214
        applicationContext.registerBeanDefinition("hibernateProperties", hibernatePropBean);
215

    
216
        XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(applicationContext);
217
        progressMonitor.subTask("Registering resources.");
218
        xmlReader.loadBeanDefinitions(applicationContextResource);
219
        progressMonitor.worked(1);
220

    
221
        //omitTerms
222
        if (omitTermLoading == true){
223
            String initializerName = "persistentTermInitializer";
224
            BeanDefinition beanDef = applicationContext.getBeanDefinition(initializerName);
225
            MutablePropertyValues values = beanDef.getPropertyValues();
226
            values.addPropertyValue("omit", omitTermLoading);
227
        }
228

    
229
        if (listeners != null){
230
            for(ApplicationListener listener : listeners){
231
                applicationContext.addApplicationListener(listener);
232
            }
233
        }
234

    
235
//		String message = "Start application context. This might take a while ...";
236
////		progressMonitor.subTask(message);
237
//		SubProgressMonitor subMonitor= new SubProgressMonitor(progressMonitor, 10);
238
//		subMonitor.beginTask(message, 2);
239
//		applicationContext.setProgressMonitor(subMonitor);
240

    
241
        applicationContext.refresh(new SubProgressMonitor(progressMonitor, refreshTasks));
242
        applicationContext.start();
243
//		progressMonitor.worked(1);
244

    
245
        progressMonitor.subTask("Cleaning up.");
246
        setApplicationContext(applicationContext);
247
        progressMonitor.worked(1);
248

    
249
        //initialize user and metaData for new databases
250
        int userCount = getUserService().count(User.class);
251
        if (userCount == 0 ){
252
            progressMonitor.subTask("Creating Admin User");
253
            createAdminUser();
254
        }
255
        progressMonitor.worked(1);
256

    
257
        //CDM Meta Data
258
        int metaDataCount = getCommonService().getCdmMetaData().size();
259
        if (metaDataCount == 0){
260
            progressMonitor.subTask("Creating Meta Data");
261
            createMetadata();
262
        }
263
        progressMonitor.worked(1);
264

    
265
        progressMonitor.done();
266
        return true;
267
    }
268

    
269
    protected void createAdminUser(){
270
        User firstUser = User.NewInstance("admin", "00000");
271
        getUserService().save(firstUser);
272

    
273
        GrantedAuthorityImpl role_admin = GrantedAuthorityImpl.NewInstance();
274
        role_admin.setAuthority("ROLE_ADMIN");
275
        Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
276
        authorities.add(role_admin);
277
        firstUser.setGrantedAuthorities(authorities);
278

    
279
        logger.info("Admin user created.");
280
    }
281

    
282
    protected void createMetadata(){
283
        List<CdmMetaData> metaData = CdmMetaData.defaultMetaData();
284
        getCommonService().saveAllMetaData(metaData);
285
        logger.info("Metadata created.");
286
    }
287

    
288

    
289
    /**
290
     * Tests if some DefinedTermsAreMissing.
291
     * @return true, if at least one is missing, else false
292
     */
293
    public boolean testDefinedTermsAreMissing(){
294
        UUID englishUuid = UUID.fromString("e9f8cdb7-6819-44e8-95d3-e2d0690c3523");
295
        DefinedTermBase<?> english = this.getTermService().load(englishUuid);
296
        if ( english == null || ! english.getUuid().equals(englishUuid)){
297
            return true;
298
        }else{
299
            return false;
300
        }
301
    }
302

    
303

    
304
    /**
305
     * Changes the ApplicationContext to the new dataSource
306
     * @param dataSource
307
     */
308
    public boolean changeDataSource(ICdmDataSource dataSource){
309
        //logger.info("Change datasource to : " + dataSource);
310
        return setNewDataSource(dataSource, DbSchemaValidation.VALIDATE, false, null);
311
    }
312

    
313
    /**
314
     * Changes the ApplicationContext to the new dataSource
315
     * @param dataSource
316
     * @param dbSchemaValidation
317
     */
318
    public boolean changeDataSource(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation){
319
        //logger.info("Change datasource to : " + dataSource);
320
        return setNewDataSource(dataSource, dbSchemaValidation, false, null);
321
    }
322

    
323
    /**
324
     * Changes the ApplicationContext to the new dataSource
325
     * @param dataSource
326
     * @param dbSchemaValidation
327
     * @param omitTermLoading
328
     */
329
    public boolean changeDataSource(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading){
330
        logger.info("Change datasource to : " + dataSource);
331
        return setNewDataSource(dataSource, dbSchemaValidation, omitTermLoading, null);
332
    }
333

    
334
    /**
335
     * Changes the ApplicationContext to the new dataSource
336
     * @param dataSource
337
     * @param dbSchemaValidation
338
     * @param omitTermLoading
339
     */
340
    public boolean changeDataSource(ICdmDataSource dataSource, DbSchemaValidation dbSchemaValidation, boolean omitTermLoading, List<ApplicationListener> listeners){
341
        logger.info("Change datasource to : " + dataSource);
342
        return setNewDataSource(dataSource, dbSchemaValidation, omitTermLoading, listeners);
343
    }
344

    
345
    /**
346
     * Sets a new application Context.
347
     * @param ac
348
     */
349
    public void setApplicationContext(AbstractApplicationContext ac){
350
        closeApplicationContext(); //closes old application context if necessary
351
        applicationContext = ac;
352
        applicationContext.registerShutdownHook();
353
        init();
354
    }
355

    
356
    /* (non-Javadoc)
357
     * @see java.lang.Object#finalize()
358
     */
359
    public void finalize(){
360
        close();
361
    }
362

    
363
    /**
364
     * closes the application
365
     */
366
    public void close(){
367
        closeApplicationContext();
368
    }
369

    
370
    /**
371
     * closes the application context
372
     */
373
    protected void closeApplicationContext(){
374
        if (applicationContext != null){
375
            logger.info("Close ApplicationContext");
376
            applicationContext.close();
377
        }
378
    }
379

    
380
    protected void init(){
381
        logger.debug("Init " +  this.getClass().getName() + " ... ");
382
        if (logger.isDebugEnabled()){for (String beanName : applicationContext.getBeanDefinitionNames()){ logger.debug(beanName);}}
383
        //TODO delete next row (was just for testing)
384
        if (logger.isInfoEnabled()){
385
            logger.info("Registered Beans: ");
386
            String[] beanNames = applicationContext.getBeanDefinitionNames();
387
            for (String beanName : beanNames){
388
                logger.info(beanName);
389
            }
390
        }
391
        configuration = (ICdmApplicationConfiguration)applicationContext.getBean("cdmApplicationDefaultConfiguration");
392
        getDatabaseService().setApplicationController(this);
393
    }
394

    
395

    
396

    
397
    /* ******  Services *********/
398
    public final INameService getNameService(){
399
        return configuration.getNameService();
400
    }
401

    
402
    public final ITaxonService getTaxonService(){
403
        return configuration.getTaxonService();
404
    }
405

    
406
    public final IClassificationService getClassificationService(){
407
        return configuration.getClassificationService();
408
    }
409

    
410
    public final ITaxonNodeService getTaxonNodeService(){
411
        return configuration.getTaxonNodeService();
412
    }
413

    
414
    public final IReferenceService getReferenceService(){
415
        return configuration.getReferenceService();
416
    }
417

    
418
    public final IAgentService getAgentService(){
419
        return configuration.getAgentService();
420
    }
421

    
422
    public final IDatabaseService getDatabaseService(){
423
        return configuration.getDatabaseService();
424
    }
425

    
426
    public final ITermService getTermService(){
427
        return configuration.getTermService();
428
    }
429

    
430
    public final IDescriptionService getDescriptionService(){
431
        return configuration.getDescriptionService();
432
    }
433

    
434
    public final IOccurrenceService getOccurrenceService(){
435
        return configuration.getOccurrenceService();
436
    }
437

    
438
    public final IMediaService getMediaService(){
439
        return configuration.getMediaService();
440
    }
441

    
442
    public final ICommonService getCommonService(){
443
        return configuration.getCommonService();
444
    }
445

    
446
    public final ILocationService getLocationService(){
447
        return configuration.getLocationService();
448
    }
449

    
450
    public final IUserService getUserService(){
451
        return configuration.getUserService();
452
    }
453

    
454
    public final IGrantedAuthorityService getGrantedAuthorityService(){
455
        return configuration.getGrantedAuthorityService();
456
    }
457

    
458
    public IGroupService getGroupService() {
459
        return configuration.getGroupService();
460
    }
461

    
462
    public final ICollectionService getCollectionService(){
463
        return configuration.getCollectionService();
464
    }
465

    
466
    public final IFeatureTreeService getFeatureTreeService(){
467
        return configuration.getFeatureTreeService();
468
    }
469

    
470
    public final IFeatureNodeService getFeatureNodeService(){
471
        return configuration.getFeatureNodeService();
472
    }
473

    
474
    public final IVocabularyService getVocabularyService(){
475
        return configuration.getVocabularyService();
476
    }
477

    
478
    public final IIdentificationKeyService getIdentificationKeyService(){
479
        return configuration.getIdentificationKeyService();
480
    }
481

    
482
    public final IPolytomousKeyService getPolytomousKeyService(){
483
        return configuration.getPolytomousKeyService();
484
    }
485

    
486
    public final IPolytomousKeyNodeService getPolytomousKeyNodeService(){
487
        return configuration.getPolytomousKeyNodeService();
488
    }
489

    
490
    public final IService<CdmBase> getMainService(){
491
        return configuration.getMainService();
492
    }
493

    
494
    public final IWorkingSetService getWorkingSetService(){
495
        return configuration.getWorkingSetService();
496
    }
497

    
498
    public final ConversationHolder NewConversation(){
499
        //return (ConversationHolder)applicationContext.getBean("conversationHolder");
500
        return configuration.NewConversation();
501
    }
502

    
503

    
504
    /* **** Security ***** */
505

    
506
    /* (non-Javadoc)
507
     * @see eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration#getAuthenticationManager()
508
     */
509
    public final ProviderManager getAuthenticationManager(){
510
        return configuration.getAuthenticationManager();
511
    }
512

    
513

    
514
    public PermissionEvaluator getPermissionEvaluator() {
515
        return configuration.getPermissionEvaluator();
516
    }
517

    
518
    /**
519
     * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
520
     *
521
     * @param targetDomainObject
522
     * @param permission
523
     * @return
524
     */
525
    public boolean currentAuthentiationHasPermissions(CdmBase targetDomainObject, EnumSet<CRUD> permission){
526
        SecurityContext context = SecurityContextHolder.getContext();
527
        return getPermissionEvaluator().hasPermission(context.getAuthentication(), targetDomainObject, permission);
528
    }
529

    
530

    
531
    @Override
532
    public final PlatformTransactionManager getTransactionManager() {
533
        return configuration.getTransactionManager();
534
    }
535

    
536
    public final Object getBean(String name){
537
        return this.applicationContext.getBean(name);
538
    }
539

    
540
    /*
541
     * OLD TRANSACTION STUFF
542
     */
543

    
544
    /* **** flush ***********/
545
    public void flush() {
546
        SessionFactory sf = (SessionFactory)applicationContext.getBean("sessionFactory");
547
        sf.getCurrentSession().flush();
548
    }
549

    
550
    public SessionFactory getSessionFactory(){
551
        return (SessionFactory)applicationContext.getBean("sessionFactory");
552
    }
553

    
554
    public TransactionStatus startTransaction() {
555
        return startTransaction(false);
556
    }
557

    
558
    public TransactionStatus startTransaction(Boolean readOnly) {
559
        return configuration.startTransaction(readOnly);
560
    }
561

    
562
    public void commitTransaction(TransactionStatus txStatus){
563
        PlatformTransactionManager txManager = configuration.getTransactionManager();
564
        txManager.commit(txStatus);
565
        return;
566
    }
567

    
568
}
(1-1/5)