Project

General

Profile

Download (21.5 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
        CdmApplicationState.setCdmServiceCacher(new CdmServiceCacher());
269
        
270
    }
271

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

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

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

    
310
    /*
311
     * CONVERSATIONS
312
     */
313

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

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

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

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

    
354
    }
355

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

    
373
        return service;
374
    }
375

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

    
383
    }
384

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

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

    
410

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

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

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

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

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

    
468
    /*
469
     * LANGUAGE
470
     */
471

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

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

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

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

    
511
    /*
512
     * LOGIN
513
     */
514

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

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

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

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

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

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

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

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

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

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

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

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

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

    
617

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

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

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

    
660
}
(2-2/13)