Project

General

Profile

Download (21.9 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 * Copyright (C) 2007 EDIT
3
 * European Distributed Institute of Taxonomy
4
 * http://www.e-taxonomy.eu
5
 *
6
 * The contents of this file are subject to the Mozilla Public License Version 1.1
7
 * See LICENSE.TXT at the top of this package for the full license terms.
8
 */
9

    
10
package eu.etaxonomy.taxeditor.store;
11

    
12
import java.util.EnumSet;
13

    
14
import org.eclipse.core.runtime.IProgressMonitor;
15
import org.eclipse.core.runtime.jobs.Job;
16
import org.eclipse.swt.widgets.Display;
17
import org.springframework.core.io.ClassPathResource;
18
import org.springframework.core.io.Resource;
19
import org.springframework.security.access.PermissionEvaluator;
20
import org.springframework.security.authentication.AuthenticationManager;
21
import org.springframework.security.core.Authentication;
22
import org.springframework.security.core.context.SecurityContext;
23
import org.springframework.security.core.context.SecurityContextHolder;
24

    
25
import eu.etaxonomy.cdm.api.application.CdmApplicationException;
26
import eu.etaxonomy.cdm.api.application.CdmApplicationRemoteController;
27
import eu.etaxonomy.cdm.api.application.CdmApplicationState;
28
import eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration;
29
import eu.etaxonomy.cdm.api.cache.CdmServiceCacher;
30
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
31
import eu.etaxonomy.cdm.api.service.IAgentService;
32
import eu.etaxonomy.cdm.api.service.ICollectionService;
33
import eu.etaxonomy.cdm.api.service.ICommonService;
34
import eu.etaxonomy.cdm.api.service.INameService;
35
import eu.etaxonomy.cdm.api.service.IOccurrenceService;
36
import eu.etaxonomy.cdm.api.service.IPolytomousKeyService;
37
import eu.etaxonomy.cdm.api.service.IReferenceService;
38
import eu.etaxonomy.cdm.api.service.IService;
39
import eu.etaxonomy.cdm.api.service.IUserService;
40
import eu.etaxonomy.cdm.api.service.molecular.IAmplificationService;
41
import eu.etaxonomy.cdm.api.service.molecular.IPrimerService;
42
import eu.etaxonomy.cdm.config.ICdmSource;
43
import eu.etaxonomy.cdm.database.DbSchemaValidation;
44
import eu.etaxonomy.cdm.model.agent.AgentBase;
45
import eu.etaxonomy.cdm.model.common.CdmBase;
46
import eu.etaxonomy.cdm.model.common.Language;
47
import eu.etaxonomy.cdm.model.common.User;
48
import eu.etaxonomy.cdm.model.description.PolytomousKey;
49
import eu.etaxonomy.cdm.model.molecular.Amplification;
50
import eu.etaxonomy.cdm.model.molecular.Primer;
51
import eu.etaxonomy.cdm.model.name.NonViralName;
52
import eu.etaxonomy.cdm.model.occurrence.Collection;
53
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
54
import eu.etaxonomy.cdm.model.reference.Reference;
55
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
56
import eu.etaxonomy.cdm.persistence.hibernate.permission.ICdmPermissionEvaluator;
57
import eu.etaxonomy.cdm.persistence.hibernate.permission.Role;
58
import eu.etaxonomy.taxeditor.datasource.CdmDataSourceRepository;
59
import eu.etaxonomy.taxeditor.io.ExportManager;
60
import eu.etaxonomy.taxeditor.io.ImportManager;
61
import eu.etaxonomy.taxeditor.model.MessagingUtils;
62
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
63
import eu.etaxonomy.taxeditor.remoting.cache.CdmRemoteCacheManager;
64
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionManager;
65
import eu.etaxonomy.taxeditor.session.mock.MockCdmEntitySessionManager;
66
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
67
import eu.etaxonomy.taxeditor.ui.dialog.RemotingLoginDialog;
68
import eu.etaxonomy.taxeditor.util.ProgressMonitorClientManager;
69
import eu.etaxonomy.taxeditor.webapp.CDMServer;
70

    
71
/**
72
 * This implementation of ICdmDataRepository depends on hibernate sessions to
73
 * store the data correctly for the current session. No state is held in this
74
 * class.
75
 *
76
 * Only methods that either get or manipulate data are exposed here. So this
77
 * class acts as a facade for the methods in cdmlib-service.
78
 *
79
 * @author n.hoffmann
80
 * @created 17.03.2009
81
 * @version 1.0
82
 */
83
public class CdmStore {
84

    
85
    private static final Resource DEFAULT_APPLICATION_CONTEXT = new ClassPathResource(
86
            "/eu/etaxonomy/cdm/editorApplicationContext.xml",
87
            TaxeditorStorePlugin.class);
88
    private static final DbSchemaValidation DEFAULT_DB_SCHEMA_VALIDATION = DbSchemaValidation.VALIDATE;
89

    
90
    private static CdmStore instance;
91

    
92
    //private final ICdmApplicationConfiguration applicationConfiguration;
93

    
94
    private static ContextManager contextManager = new ContextManager();
95

    
96
    private static LoginManager loginManager = new LoginManager();
97

    
98
    private static TermManager termManager = new TermManager();
99

    
100
    private static SearchManager searchManager = new SearchManager();
101

    
102
    private static EditorManager editorManager = new EditorManager();
103

    
104
    private static UseObjectStore useObjectInitializer = new UseObjectStore();
105

    
106
    private static ProgressMonitorClientManager progressMonitorClientManager = new ProgressMonitorClientManager();
107

    
108
    private static CdmStoreConnector job;
109

    
110
    private static CDMServer managedServer;
111

    
112
    private Language language;
113

    
114
    private ICdmSource cdmSource;
115

    
116
    private boolean isConnected;
117

    
118

    
119

    
120
    /**
121
     * <p>
122
     * getDefault
123
     * </p>
124
     *
125
     * @return a {@link eu.etaxonomy.taxeditor.store.CdmStore} object.
126
     */
127
    protected static CdmStore getDefault(boolean connecting){
128
        if (instance != null && instance.isConnected) {
129
            return instance;
130
        } else{// if (instance == null || !instance.isConnected) {
131
            if (connecting){
132
                MessagingUtils.dataSourceNotAvailableWarningDialog(instance);
133
            }else{
134
                MessagingUtils.noDataSourceWarningDialog(instance);
135
            }
136

    
137

    
138
            return null;
139
        }
140
    }
141
    /**
142
     * <p>
143
     * getDefault
144
     * </p>
145
     *
146
     * @return a {@link eu.etaxonomy.taxeditor.store.CdmStore} object.
147
     */
148
    protected static CdmStore getDefault(){
149
       return getDefault(false);
150
    }
151

    
152
    /**
153
     * Initialize the with the last edited datasource
154
     */
155
    public static void connect() {
156

    
157
        ICdmSource cdmSource;
158
        try {
159

    
160
            cdmSource = CdmDataSourceRepository.getCurrentCdmSource();
161
            connect(cdmSource);
162
        } catch (Exception e) {
163
            MessagingUtils.messageDialog("Connection to CDM Source Failed", CdmStore.class, "Could not connect to target CDM Source", e);
164
        }
165

    
166

    
167
    }
168

    
169
    /**
170
     * Initialize with a specific datasource
171
     *
172
     * @param datasource
173
     *            a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
174
     */
175
    public static void connect(ICdmSource cdmSource) {
176
        connect(cdmSource, DEFAULT_DB_SCHEMA_VALIDATION,
177
                DEFAULT_APPLICATION_CONTEXT);
178
    }
179

    
180
    public static void connect(ICdmSource cdmSource, RemotingLoginDialog loginDialog) {
181
        connect(cdmSource,
182
                DEFAULT_DB_SCHEMA_VALIDATION,
183
                DEFAULT_APPLICATION_CONTEXT,
184
                loginDialog);
185
    }
186

    
187
    /**
188
     * Initialize and provide
189
     *
190
     * @param datasource
191
     * @param dbSchemaValidation
192
     * @param applicationContextBean
193
     */
194
    private static void connect(final ICdmSource cdmSource,
195
            final DbSchemaValidation dbSchemaValidation,
196
            final Resource applicationContextBean) {
197

    
198
        MessagingUtils.info("Connecting to datasource: " + cdmSource);
199

    
200
        job = new CdmStoreConnector(Display.getDefault(), cdmSource,
201
                dbSchemaValidation, applicationContextBean);
202
        job.setUser(true);
203
        job.setPriority(Job.BUILD);
204
        job.schedule();
205

    
206
    }
207

    
208
    private static void connect(final ICdmSource cdmSource,
209
            final DbSchemaValidation dbSchemaValidation,
210
            final Resource applicationContextBean,
211
            RemotingLoginDialog remotingLoginDialog) {
212
        RemotingLoginDialog loginDialog = remotingLoginDialog;
213
        if(isActive()) {
214
            // before we connect we clear the entity caches and the sessions
215
            CdmRemoteCacheManager.removeEntityCaches();
216
            if(getCurrentSessionManager(true) != null) {
217
                getCurrentSessionManager(true).disposeAll();
218
            }
219
        }
220
        MessagingUtils.info("Connecting to datasource: " + cdmSource);
221

    
222
        job = new CdmStoreConnector(Display.getDefault(),
223
                cdmSource,
224
                dbSchemaValidation,
225
                applicationContextBean);
226
        job.start(loginDialog);
227

    
228
    }
229

    
230
    public static boolean isConnecting() {
231
        return job != null && job.getState() == Job.RUNNING;
232
    }
233

    
234
    /**
235
     * Closes the current application context
236
     *
237
     * @param monitor
238
     *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
239
     */
240
    public static void close(final IProgressMonitor monitor) {
241
        Display.getDefault().asyncExec(new Runnable() {
242
            /*
243
             * (non-Javadoc)
244
             *
245
             * @see java.lang.Runnable#run()
246
             */
247
            @Override
248
            public void run() {
249
                getContextManager().notifyContextAboutToStop(monitor);
250
                if ((monitor == null || (!monitor.isCanceled()) && isActive())) {
251
                    getContextManager().notifyContextStop(monitor);
252
                    instance.close();
253
                }
254
            }
255
        });
256
    }
257

    
258
    public static void close(IProgressMonitor monitor, boolean async) {
259
        if(async) {
260
            close(monitor);
261
        } else {
262
            getContextManager().notifyContextAboutToStop(monitor);
263
            if ((monitor == null || (!monitor.isCanceled()) && isActive())) {
264
                getContextManager().notifyContextStop(monitor);
265
                instance.close();
266
            }
267
        }
268

    
269
    }
270
    private void close() {
271
        isConnected = false;
272
        cdmSource = null;
273
        CdmApplicationState.dispose();
274
    }
275

    
276
    static void setInstance(ICdmApplicationConfiguration applicationController,
277
            ICdmSource cdmSource) {
278
        instance = new CdmStore(applicationController, cdmSource);
279
        CdmApplicationState.setCdmServiceCacher(new CdmServiceCacher());
280

    
281
    }
282

    
283
    private CdmStore(ICdmApplicationConfiguration applicationController,
284
            ICdmSource cdmSource) {
285
        CdmApplicationState.setCurrentAppConfig(applicationController);
286
        CdmApplicationState.setCurrentDataChangeService(new CdmUIDataChangeService());
287
        this.cdmSource = cdmSource;
288
        isConnected = true;
289
    }
290

    
291
    /**
292
     * All calls to the datastore require
293
     *
294
     * @return
295
     */
296
    private ICdmApplicationConfiguration getApplicationConfiguration() {
297
        try {
298
            return CdmApplicationState.getCurrentAppConfig();
299
        } catch (Exception e) {
300
            MessagingUtils.error(CdmStore.class, e);
301
        }
302
        return null;
303
    }
304

    
305
    /**
306
     * <p>
307
     * getCurrentApplicationController
308
     * </p>
309
     *
310
     * @return a
311
     *         {@link eu.etaxonomy.cdm.remote.api.application.CdmApplicationController}
312
     *         object.
313
     */
314
    public static ICdmApplicationConfiguration getCurrentApplicationConfiguration() {
315
        if (getDefault() != null) {
316
            return getDefault().getApplicationConfiguration();
317
        }
318
        return null;
319
    }
320

    
321
    /*
322
     * CONVERSATIONS
323
     */
324

    
325
    /**
326
     * Creates a new conversation, binds resources to the conversation and start
327
     * a transaction for this conversation.
328
     *
329
     * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
330
     *         object.
331
     */
332
    public static ConversationHolder createConversation() {
333
        ConversationHolder conversation = getCurrentApplicationConfiguration()
334
                .NewConversation();
335
        try {
336
            conversation.startTransaction();
337
        }catch(Exception e){
338
            MessagingUtils.messageDialog("No database connection", CdmStore.class, "No database connection available", e);
339
        }
340
        return conversation;
341
    }
342

    
343
    //FIXME:Remoting should be removed after moving completely to remoting
344
    private MockCdmEntitySessionManager mockCdmEntitySessionManager;
345

    
346
    private ICdmEntitySessionManager getSessionManager() {
347
        //FIXME:Remoting we should only have CdmApplicationRemoteConfiguration after move to remoting
348
        //               bad hack which should be finally removed
349
        if(getCurrentApplicationConfiguration() instanceof CdmApplicationRemoteController) {
350
            return ((CdmApplicationRemoteController)getCurrentApplicationConfiguration()).getCdmEntitySessionManager();
351
        } else {
352
            if(mockCdmEntitySessionManager == null) {
353
                mockCdmEntitySessionManager = new MockCdmEntitySessionManager();
354
            }
355
            return mockCdmEntitySessionManager;
356
        }
357
    }
358
    public static  ICdmEntitySessionManager getCurrentSessionManager() {
359
        return getCurrentSessionManager(false);
360
    }
361

    
362

    
363
    public static  ICdmEntitySessionManager getCurrentSessionManager(boolean connecting) {
364
        if (getDefault(connecting) != null) {
365
            return getDefault(connecting).getSessionManager();
366
        }
367
        return null;
368

    
369
    }
370

    
371
    /**
372
     * Generic method that will scan the getters of {@link ICdmApplicationConfiguration} for the given service
373
     * interface. If a matching getter is found the according service implementation is returned by
374
     * invoking the getter otherwise the method returns <code>null</code>.
375
     *
376
     * @param <T>
377
     * @param serviceClass
378
     * @return the configured implementation of <code>serviceClass</code> or <code>null</code>
379
     */
380
    public static <T extends IService> T getService(Class<T> serviceClass) {
381
        T service = null;
382
        try {
383
            service = CdmApplicationState.getService(serviceClass);
384
        } catch (CdmApplicationException cae) {
385
            MessagingUtils.error(CdmStore.class, cae);
386
        }
387

    
388
        return service;
389
    }
390

    
391
    /**
392
     * @see #getService(Class)
393
     * As ICommonService is not extending IService we need a specific request here
394
     */
395
    public static ICommonService getCommonService() {
396
        return CdmApplicationState.getCommonService();
397

    
398
    }
399

    
400
    /**
401
     * <p>
402
     * getAuthenticationManager
403
     * </p>
404
     *
405
     * @return a
406
     *         {@link org.springframework.security.authentication.ProviderManager}
407
     *         object.
408
     */
409
    public static AuthenticationManager getAuthenticationManager() {
410
        return getCurrentApplicationConfiguration().getAuthenticationManager();
411
    }
412

    
413
    /**
414
     * <p>
415
     * getAuthenticationManager
416
     * </p>
417
     *
418
     * @return a
419
     *         {@link ICdmPermissionEvaluator} object.
420
     */
421
    public static ICdmPermissionEvaluator getPermissionEvaluator() {
422
        return getCurrentApplicationConfiguration().getPermissionEvaluator();
423
    }
424

    
425

    
426
    /*
427
     * SECURITY RELATED CONVENIENCE METHODS
428
     */
429

    
430
    /**
431
     * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
432
     *
433
     * @param targetDomainObject
434
     * @param permission
435
     * @return
436
     */
437
    public static boolean currentAuthentiationHasPermission(CdmBase targetDomainObject, EnumSet<CRUD> permission){
438
        //TODO use getCurrentApplicationConfiguration().currentAuthentiationHasPermission(CdmBase targetDomainObject, Operation permission) instead
439
        SecurityContext context = SecurityContextHolder.getContext();
440
        PermissionEvaluator pe = getPermissionEvaluator();
441
        boolean hasPermission = false;
442
        try {
443
            hasPermission = getPermissionEvaluator().hasPermission(context.getAuthentication(), targetDomainObject,
444
                    permission);
445
        } catch (org.springframework.security.access.AccessDeniedException e) {
446
            /* IGNORE */
447
        }
448
        return hasPermission;
449
    }
450

    
451
    /**
452
     * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
453
     *
454
     * @param targetDomainObject
455
     * @param permission
456
     * @return
457
     */
458
    public static boolean currentAuthentiationHasPermission(Class<? extends CdmBase> targetType, EnumSet<CRUD> permission){
459
        boolean hasPermission = false;
460
        try {
461
            hasPermission = getPermissionEvaluator().hasPermission(getCurrentAuthentiation(), null, targetType.getName(), permission);
462
        } catch (org.springframework.security.access.AccessDeniedException e) {
463
            /* IGNORE */
464
        }
465
        return hasPermission;
466
    }
467

    
468
    public static boolean currentAuthentiationHasOneOfRoles(Role ... roles){
469
        boolean hasPermission = false;
470
        try {
471
            hasPermission =  getPermissionEvaluator().hasOneOfRoles(getCurrentAuthentiation(), roles);
472
        } catch (org.springframework.security.access.AccessDeniedException e) {
473
            /* IGNORE */
474
        }
475
        return hasPermission;
476
    }
477

    
478
    public static Authentication getCurrentAuthentiation() {
479
        SecurityContext context = SecurityContextHolder.getContext();
480
        return context.getAuthentication();
481
    }
482

    
483
    /*
484
     * LANGUAGE
485
     */
486

    
487
    /**
488
     * Provides access to the global default language set in the application preferences.
489
     *
490
     * @return a {@link eu.etaxonomy.cdm.model.common.Language} object.
491
     */
492
    public static Language getDefaultLanguage() {
493
        if (getDefault().getLanguage() == null) {
494
            getDefault().setLanguage(PreferencesUtil.getGlobalLanguage());
495
        }
496
        return getDefault().getLanguage();
497
    }
498

    
499
    /**
500
     * <p>
501
     * setDefaultLanguage
502
     * </p>
503
     *
504
     * @param language
505
     *            a {@link eu.etaxonomy.cdm.model.common.Language} object.
506
     */
507
    public static void setDefaultLanguage(Language language) {
508
        getDefault().setLanguage(language);
509
    }
510

    
511
    /**
512
     * @return the language
513
     */
514
    private Language getLanguage() {
515
        return language;
516
    }
517

    
518
    /**
519
     * @param language
520
     *            the language to set
521
     */
522
    private void setLanguage(Language language) {
523
        this.language = language;
524
    }
525

    
526
    /*
527
     * LOGIN
528
     */
529

    
530
    /**
531
     * <p>
532
     * Getter for the field <code>loginManager</code>.
533
     * </p>
534
     *
535
     * @return a {@link eu.etaxonomy.taxeditor.store.LoginManager} object.
536
     */
537
    public static LoginManager getLoginManager() {
538
        return loginManager;
539
    }
540

    
541
    /**
542
     * <p>
543
     * Getter for the field <code>contextManager</code>.
544
     * </p>
545
     *
546
     * @return a {@link eu.etaxonomy.taxeditor.store.ContextManager} object.
547
     */
548
    public static ContextManager getContextManager() {
549
        return contextManager;
550
    }
551

    
552
    public static TermManager getTermManager() {
553
        return termManager;
554
    }
555

    
556
    public static SearchManager getSearchManager() {
557
        return searchManager;
558
    }
559

    
560
    public static EditorManager getEditorManager() {
561
        return editorManager;
562
    }
563

    
564
    public static ProgressMonitorClientManager getProgressMonitorClientManager() {
565
        return progressMonitorClientManager;
566
    }
567

    
568
    /*
569
     * IMPORT/EXPORT FACTORIES
570
     */
571

    
572
    /**
573
     * <p>
574
     * Getter for the field <code>importHandler</code>.
575
     * </p>
576
     *
577
     * @return a {@link eu.etaxonomy.taxeditor.io.ImportManager} object.
578
     */
579
    public static ImportManager getImportManager() {
580
        return ImportManager.NewInstance(getCurrentApplicationConfiguration());
581
    }
582

    
583
    /**
584
     * <p>
585
     * Getter for the field <code>exportHandler</code>.
586
     * </p>
587
     *
588
     * @return a {@link eu.etaxonomy.taxeditor.io.ExportManager} object.
589
     */
590
    public static ExportManager getExportManager() {
591
        return ExportManager.NewInstance(getCurrentApplicationConfiguration());
592
    }
593

    
594
    /**
595
     * Whether this CdmStore is currently connected to a datasource
596
     *
597
     * @return a boolean.
598
     */
599
    public static boolean isActive() {
600
        return instance != null && instance.isConnected;
601
    }
602

    
603
    public static ICdmSource getActiveCdmSource() {
604
        if (isActive()) {
605
            return instance.getCdmSource();
606
        }
607
        return null;
608
    }
609

    
610
    /**
611
     * <p>
612
     * getDataSource
613
     * </p>
614
     *
615
     * @return a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
616
     * @deprecated currently retained for backward compatibility - use {@link getActiveCdmSource()} instead
617
     */
618
    //	public static ICdmDataSource getDataSource() {
619
    //		if (isActive()) {
620
    //			return (ICdmDataSource)instance.getCdmSource();
621
    //		}
622
    //		return null;
623
    //	}
624

    
625
    /**
626
     * @return
627
     */
628
    private ICdmSource getCdmSource() {
629
        return cdmSource;
630
    }
631

    
632

    
633
    public static <T extends CdmBase> IService<T> getService(T cdmBase){
634
        IService<T> service = null;
635
        if(cdmBase!=null){
636
            //get corresponding service
637
            if(cdmBase.isInstanceOf(Reference.class)){
638
                service = (IService<T>) getService(IReferenceService.class);
639
            }
640
            else if (cdmBase.isInstanceOf(AgentBase.class)){
641
                service = (IService<T>) getService(IAgentService.class);
642
            }
643
            else if (cdmBase instanceof NonViralName) {
644
                service = (IService<T>) getService(INameService.class);
645
            }
646
            else if (cdmBase instanceof SpecimenOrObservationBase) {
647
                service = (IService<T>) getService(IOccurrenceService.class);
648
            }
649
            else if (cdmBase instanceof Collection) {
650
                service = (IService<T>) getService(ICollectionService.class);
651
            }
652
            else if (cdmBase instanceof User) {
653
                service = (IService<T>) getService(IUserService.class);
654
            }
655
            else if (cdmBase instanceof Primer) {
656
                service = (IService<T>) getService(IPrimerService.class);
657
            }
658
            else if (cdmBase instanceof Amplification) {
659
                service = (IService<T>) getService(IAmplificationService.class);
660
            } else if (cdmBase instanceof PolytomousKey) {
661
                service = (IService<T>) getService(IPolytomousKeyService.class);
662
            }
663
        }
664
        return service;
665
    }
666

    
667
    public static void setManagedServer(CDMServer server) {
668
        managedServer = server;
669
    }
670

    
671
    public static CDMServer getManagedServer() {
672
        return managedServer;
673
    }
674

    
675
}
(2-2/13)