Project

General

Profile

Download (21.6 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.AbstractUtility;
62
import eu.etaxonomy.taxeditor.model.MessagingUtils;
63
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
64
import eu.etaxonomy.taxeditor.remoting.cache.CdmRemoteCacheManager;
65
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionManager;
66
import eu.etaxonomy.taxeditor.session.mock.MockCdmEntitySessionManager;
67
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
68
import eu.etaxonomy.taxeditor.ui.dialog.RemotingLoginDialog;
69
import eu.etaxonomy.taxeditor.util.ProgressMonitorClientManager;
70
import eu.etaxonomy.taxeditor.view.datasource.CdmDataSourceViewPart;
71
import eu.etaxonomy.taxeditor.webapp.CDMServer;
72

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

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

    
92
    private static CdmStore instance;
93

    
94
    //private final ICdmApplicationConfiguration applicationConfiguration;
95

    
96
    private static ContextManager contextManager = new ContextManager();
97

    
98
    private static LoginManager loginManager = new LoginManager();
99

    
100
    private static TermManager termManager = new TermManager();
101

    
102
    private static SearchManager searchManager = new SearchManager();
103

    
104
    private static EditorManager editorManager = new EditorManager();
105

    
106
    private static UseObjectStore useObjectInitializer = new UseObjectStore();
107

    
108
    private static ProgressMonitorClientManager progressMonitorClientManager = new ProgressMonitorClientManager();
109

    
110
    private static CdmStoreConnector job;
111

    
112
    private static CDMServer managedServer;
113

    
114
    private Language language;
115

    
116
    private ICdmSource cdmSource;
117

    
118
    private boolean isConnected;
119

    
120

    
121

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

    
134
            MessagingUtils.noDataSourceWarningDialog(instance);
135

    
136
            AbstractUtility.showView(CdmDataSourceViewPart.ID);
137
            return null;
138
        }
139
    }
140

    
141
    /**
142
     * Initialize the with the last edited datasource
143
     */
144
    public static void connect() {
145

    
146
        ICdmSource cdmSource;
147
        try {
148

    
149
            cdmSource = CdmDataSourceRepository.getCurrentCdmSource();
150
            connect(cdmSource);
151
        } catch (Exception e) {
152
            MessagingUtils.messageDialog("Connection to CDM Source Failed", CdmStore.class, "Could not connect to target CDM Source", e);
153
        }
154

    
155

    
156
    }
157

    
158
    /**
159
     * Initialize with a specific datasource
160
     *
161
     * @param datasource
162
     *            a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
163
     */
164
    public static void connect(ICdmSource cdmSource) {
165
        connect(cdmSource, DEFAULT_DB_SCHEMA_VALIDATION,
166
                DEFAULT_APPLICATION_CONTEXT);
167
    }
168

    
169
    public static void connect(ICdmSource cdmSource, RemotingLoginDialog loginDialog) {
170
        connect(cdmSource,
171
                DEFAULT_DB_SCHEMA_VALIDATION,
172
                DEFAULT_APPLICATION_CONTEXT,
173
                loginDialog);
174
    }
175

    
176
    /**
177
     * Initialize and provide
178
     *
179
     * @param datasource
180
     * @param dbSchemaValidation
181
     * @param applicationContextBean
182
     */
183
    private static void connect(final ICdmSource cdmSource,
184
            final DbSchemaValidation dbSchemaValidation,
185
            final Resource applicationContextBean) {
186

    
187
        MessagingUtils.info("Connecting to datasource: " + cdmSource);
188

    
189
        job = new CdmStoreConnector(Display.getDefault(), cdmSource,
190
                dbSchemaValidation, applicationContextBean);
191
        job.setUser(true);
192
        job.setPriority(Job.BUILD);
193
        job.schedule();
194

    
195
    }
196

    
197
    private static void connect(final ICdmSource cdmSource,
198
            final DbSchemaValidation dbSchemaValidation,
199
            final Resource applicationContextBean,
200
            RemotingLoginDialog remotingLoginDialog) {
201
        RemotingLoginDialog loginDialog = remotingLoginDialog;
202
        if(isActive()) {
203
            // before we connect we clear the entity caches and the sessions
204
            CdmRemoteCacheManager.removeEntityCaches();
205
            if(getCurrentSessionManager() != null) {
206
                getCurrentSessionManager().disposeAll();
207
            }
208
        }
209
        MessagingUtils.info("Connecting to datasource: " + cdmSource);
210

    
211
        job = new CdmStoreConnector(Display.getDefault(),
212
                cdmSource,
213
                dbSchemaValidation,
214
                applicationContextBean);
215
        job.start(loginDialog);
216

    
217
    }
218

    
219
    public static boolean isConnecting() {
220
        return job != null && job.getState() == Job.RUNNING;
221
    }
222

    
223
    /**
224
     * Closes the current application context
225
     *
226
     * @param monitor
227
     *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
228
     */
229
    public static void close(final IProgressMonitor monitor) {
230
        Display.getDefault().asyncExec(new Runnable() {
231
            /*
232
             * (non-Javadoc)
233
             *
234
             * @see java.lang.Runnable#run()
235
             */
236
            @Override
237
            public void run() {
238
                getContextManager().notifyContextAboutToStop(monitor);
239
                if ((monitor == null || (!monitor.isCanceled()) && isActive())) {
240
                    getContextManager().notifyContextStop(monitor);
241
                    instance.close();
242
                }
243
            }
244
        });
245
    }
246

    
247
    public static void close(IProgressMonitor monitor, boolean async) {
248
        if(async) {
249
            close(monitor);
250
        } else {
251
            getContextManager().notifyContextAboutToStop(monitor);
252
            if ((monitor == null || (!monitor.isCanceled()) && isActive())) {
253
                getContextManager().notifyContextStop(monitor);
254
                instance.close();
255
            }
256
        }
257

    
258
    }
259
    private void close() {
260
        isConnected = false;
261
        cdmSource = null;
262
        CdmApplicationState.dispose();
263
    }
264

    
265
    static void setInstance(ICdmApplicationConfiguration applicationController,
266
            ICdmSource cdmSource) {
267
        instance = new CdmStore(applicationController, cdmSource);
268
        if(getCurrentSessionManager().isRemoting()) {
269
            CdmApplicationState.setCdmServiceCacher(new CdmServiceCacher());
270
        }
271
    }
272

    
273
    private CdmStore(ICdmApplicationConfiguration applicationController,
274
            ICdmSource cdmSource) {
275
        CdmApplicationState.setCurrentAppConfig(applicationController);
276
        CdmApplicationState.setCurrentDataChangeService(new CdmUIDataChangeService());
277
        this.cdmSource = cdmSource;
278
        isConnected = true;
279
    }
280

    
281
    /**
282
     * All calls to the datastore require
283
     *
284
     * @return
285
     */
286
    private ICdmApplicationConfiguration getApplicationConfiguration() {
287
        try {
288
            return CdmApplicationState.getCurrentAppConfig();
289
        } catch (Exception e) {
290
            MessagingUtils.error(CdmStore.class, e);
291
        }
292
        return null;
293
    }
294

    
295
    /**
296
     * <p>
297
     * getCurrentApplicationController
298
     * </p>
299
     *
300
     * @return a
301
     *         {@link eu.etaxonomy.cdm.remote.api.application.CdmApplicationController}
302
     *         object.
303
     */
304
    public static ICdmApplicationConfiguration getCurrentApplicationConfiguration() {
305
        if (getDefault() != null) {
306
            return getDefault().getApplicationConfiguration();
307
        }
308
        return null;
309
    }
310

    
311
    /*
312
     * CONVERSATIONS
313
     */
314

    
315
    /**
316
     * Creates a new conversation, binds resources to the conversation and start
317
     * a transaction for this conversation.
318
     *
319
     * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
320
     *         object.
321
     */
322
    public static ConversationHolder createConversation() {
323
        ConversationHolder conversation = getCurrentApplicationConfiguration()
324
                .NewConversation();
325
        try {
326
            conversation.startTransaction();
327
        }catch(Exception e){
328
            MessagingUtils.messageDialog("No database connection", CdmStore.class, "No database connection available", e);
329
        }
330
        return conversation;
331
    }
332

    
333
    //FIXME:Remoting should be removed after moving completely to remoting
334
    private MockCdmEntitySessionManager mockCdmEntitySessionManager;
335

    
336
    private ICdmEntitySessionManager getSessionManager() {
337
        //FIXME:Remoting we should only have CdmApplicationRemoteConfiguration after move to remoting
338
        //               bad hack which should be finally removed
339
        if(getCurrentApplicationConfiguration() instanceof CdmApplicationRemoteController) {
340
            return ((CdmApplicationRemoteController)getCurrentApplicationConfiguration()).getCdmEntitySessionManager();
341
        } else {
342
            if(mockCdmEntitySessionManager == null) {
343
                mockCdmEntitySessionManager = new MockCdmEntitySessionManager();
344
            }
345
            return mockCdmEntitySessionManager;
346
        }
347
    }
348

    
349
    public static  ICdmEntitySessionManager getCurrentSessionManager() {
350
        if (getDefault() != null) {
351
            return getDefault().getSessionManager();
352
        }
353
        return null;
354

    
355
    }
356

    
357
    /**
358
     * Generic method that will scan the getters of {@link ICdmApplicationConfiguration} for the given service
359
     * interface. If a matching getter is found the according service implementation is returned by
360
     * invoking the getter otherwise the method returns <code>null</code>.
361
     *
362
     * @param <T>
363
     * @param serviceClass
364
     * @return the configured implementation of <code>serviceClass</code> or <code>null</code>
365
     */
366
    public static <T extends IService> T getService(Class<T> serviceClass) {
367
        T service = null;
368
        try {
369
            service = CdmApplicationState.getService(serviceClass);
370
        } catch (CdmApplicationException cae) {
371
            MessagingUtils.error(CdmStore.class, cae);
372
        }
373

    
374
        return service;
375
    }
376

    
377
    /**
378
     * @see #getService(Class)
379
     * As ICommonService is not extending IService we need a specific request here
380
     */
381
    public static ICommonService getCommonService() {
382
        return CdmApplicationState.getCommonService();
383

    
384
    }
385

    
386
    /**
387
     * <p>
388
     * getAuthenticationManager
389
     * </p>
390
     *
391
     * @return a
392
     *         {@link org.springframework.security.authentication.ProviderManager}
393
     *         object.
394
     */
395
    public static AuthenticationManager getAuthenticationManager() {
396
        return getCurrentApplicationConfiguration().getAuthenticationManager();
397
    }
398

    
399
    /**
400
     * <p>
401
     * getAuthenticationManager
402
     * </p>
403
     *
404
     * @return a
405
     *         {@link ICdmPermissionEvaluator} object.
406
     */
407
    public static ICdmPermissionEvaluator getPermissionEvaluator() {
408
        return getCurrentApplicationConfiguration().getPermissionEvaluator();
409
    }
410

    
411

    
412
    /*
413
     * SECURITY RELATED CONVENIENCE METHODS
414
     */
415

    
416
    /**
417
     * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
418
     *
419
     * @param targetDomainObject
420
     * @param permission
421
     * @return
422
     */
423
    public static boolean currentAuthentiationHasPermission(CdmBase targetDomainObject, EnumSet<CRUD> permission){
424
        //TODO use getCurrentApplicationConfiguration().currentAuthentiationHasPermission(CdmBase targetDomainObject, Operation permission) instead
425
        SecurityContext context = SecurityContextHolder.getContext();
426
        PermissionEvaluator pe = getPermissionEvaluator();
427
        boolean hasPermission = false;
428
        try {
429
            hasPermission = getPermissionEvaluator().hasPermission(context.getAuthentication(), targetDomainObject,
430
                    permission);
431
        } catch (org.springframework.security.access.AccessDeniedException e) {
432
            /* IGNORE */
433
        }
434
        return hasPermission;
435
    }
436

    
437
    /**
438
     * @see org.springframework.security.access.PermissionEvaluator#hasPermission(org.springframework.security.core.Authentication, java.lang.Object, java.lang.Object)
439
     *
440
     * @param targetDomainObject
441
     * @param permission
442
     * @return
443
     */
444
    public static boolean currentAuthentiationHasPermission(Class<? extends CdmBase> targetType, EnumSet<CRUD> permission){
445
        boolean hasPermission = false;
446
        try {
447
            hasPermission = getPermissionEvaluator().hasPermission(getCurrentAuthentiation(), null, targetType.getName(), permission);
448
        } catch (org.springframework.security.access.AccessDeniedException e) {
449
            /* IGNORE */
450
        }
451
        return hasPermission;
452
    }
453

    
454
    public static boolean currentAuthentiationHasOneOfRoles(Role ... roles){
455
        boolean hasPermission = false;
456
        try {
457
            hasPermission =  getPermissionEvaluator().hasOneOfRoles(getCurrentAuthentiation(), roles);
458
        } catch (org.springframework.security.access.AccessDeniedException e) {
459
            /* IGNORE */
460
        }
461
        return hasPermission;
462
    }
463

    
464
    public static Authentication getCurrentAuthentiation() {
465
        SecurityContext context = SecurityContextHolder.getContext();
466
        return context.getAuthentication();
467
    }
468

    
469
    /*
470
     * LANGUAGE
471
     */
472

    
473
    /**
474
     * Provides access to the global default language set in the application preferences.
475
     *
476
     * @return a {@link eu.etaxonomy.cdm.model.common.Language} object.
477
     */
478
    public static Language getDefaultLanguage() {
479
        if (getDefault().getLanguage() == null) {
480
            getDefault().setLanguage(PreferencesUtil.getGlobalLanguage());
481
        }
482
        return getDefault().getLanguage();
483
    }
484

    
485
    /**
486
     * <p>
487
     * setDefaultLanguage
488
     * </p>
489
     *
490
     * @param language
491
     *            a {@link eu.etaxonomy.cdm.model.common.Language} object.
492
     */
493
    public static void setDefaultLanguage(Language language) {
494
        getDefault().setLanguage(language);
495
    }
496

    
497
    /**
498
     * @return the language
499
     */
500
    private Language getLanguage() {
501
        return language;
502
    }
503

    
504
    /**
505
     * @param language
506
     *            the language to set
507
     */
508
    private void setLanguage(Language language) {
509
        this.language = language;
510
    }
511

    
512
    /*
513
     * LOGIN
514
     */
515

    
516
    /**
517
     * <p>
518
     * Getter for the field <code>loginManager</code>.
519
     * </p>
520
     *
521
     * @return a {@link eu.etaxonomy.taxeditor.store.LoginManager} object.
522
     */
523
    public static LoginManager getLoginManager() {
524
        return loginManager;
525
    }
526

    
527
    /**
528
     * <p>
529
     * Getter for the field <code>contextManager</code>.
530
     * </p>
531
     *
532
     * @return a {@link eu.etaxonomy.taxeditor.store.ContextManager} object.
533
     */
534
    public static ContextManager getContextManager() {
535
        return contextManager;
536
    }
537

    
538
    public static TermManager getTermManager() {
539
        return termManager;
540
    }
541

    
542
    public static SearchManager getSearchManager() {
543
        return searchManager;
544
    }
545

    
546
    public static EditorManager getEditorManager() {
547
        return editorManager;
548
    }
549

    
550
    public static ProgressMonitorClientManager getProgressMonitorClientManager() {
551
        return progressMonitorClientManager;
552
    }
553

    
554
    /*
555
     * IMPORT/EXPORT FACTORIES
556
     */
557

    
558
    /**
559
     * <p>
560
     * Getter for the field <code>importHandler</code>.
561
     * </p>
562
     *
563
     * @return a {@link eu.etaxonomy.taxeditor.io.ImportManager} object.
564
     */
565
    public static ImportManager getImportManager() {
566
        return ImportManager.NewInstance(getCurrentApplicationConfiguration());
567
    }
568

    
569
    /**
570
     * <p>
571
     * Getter for the field <code>exportHandler</code>.
572
     * </p>
573
     *
574
     * @return a {@link eu.etaxonomy.taxeditor.io.ExportManager} object.
575
     */
576
    public static ExportManager getExportManager() {
577
        return ExportManager.NewInstance(getCurrentApplicationConfiguration());
578
    }
579

    
580
    /**
581
     * Whether this CdmStore is currently connected to a datasource
582
     *
583
     * @return a boolean.
584
     */
585
    public static boolean isActive() {
586
        return instance != null && instance.isConnected;
587
    }
588

    
589
    public static ICdmSource getActiveCdmSource() {
590
        if (isActive()) {
591
            return instance.getCdmSource();
592
        }
593
        return null;
594
    }
595

    
596
    /**
597
     * <p>
598
     * getDataSource
599
     * </p>
600
     *
601
     * @return a {@link eu.etaxonomy.cdm.database.ICdmDataSource} object.
602
     * @deprecated currently retained for backward compatibility - use {@link getActiveCdmSource()} instead
603
     */
604
    //	public static ICdmDataSource getDataSource() {
605
    //		if (isActive()) {
606
    //			return (ICdmDataSource)instance.getCdmSource();
607
    //		}
608
    //		return null;
609
    //	}
610

    
611
    /**
612
     * @return
613
     */
614
    private ICdmSource getCdmSource() {
615
        return cdmSource;
616
    }
617

    
618

    
619
    public static <T extends CdmBase> IService<T> getService(T cdmBase){
620
        IService<T> service = null;
621
        if(cdmBase!=null){
622
            //get corresponding service
623
            if(cdmBase.isInstanceOf(Reference.class)){
624
                service = (IService<T>) getService(IReferenceService.class);
625
            }
626
            else if (cdmBase.isInstanceOf(AgentBase.class)){
627
                service = (IService<T>) getService(IAgentService.class);
628
            }
629
            else if (cdmBase instanceof NonViralName) {
630
                service = (IService<T>) getService(INameService.class);
631
            }
632
            else if (cdmBase instanceof SpecimenOrObservationBase) {
633
                service = (IService<T>) getService(IOccurrenceService.class);
634
            }
635
            else if (cdmBase instanceof Collection) {
636
                service = (IService<T>) getService(ICollectionService.class);
637
            }
638
            else if (cdmBase instanceof User) {
639
                service = (IService<T>) getService(IUserService.class);
640
            }
641
            else if (cdmBase instanceof Primer) {
642
                service = (IService<T>) getService(IPrimerService.class);
643
            }
644
            else if (cdmBase instanceof Amplification) {
645
                service = (IService<T>) getService(IAmplificationService.class);
646
            } else if (cdmBase instanceof PolytomousKey) {
647
                service = (IService<T>) getService(IPolytomousKeyService.class);
648
            }
649
        }
650
        return service;
651
    }
652

    
653
    public static void setManagedServer(CDMServer server) {
654
        managedServer = server;
655
    }
656

    
657
    public static CDMServer getManagedServer() {
658
        return managedServer;
659
    }
660

    
661
}
(2-2/13)